From 61d36f42851b7cffc5d9a1681d7844064d65a432 Mon Sep 17 00:00:00 2001 From: "(no author)" <(no author)@4ea69e1a-61f1-4043-bf83-b5c94c648137> Date: Thu, 1 May 2003 08:51:47 +0000 Subject: [PATCH] This commit was manufactured by cvs2svn to create branch 'unlabeled-1.76.2'. git-svn-id: https://smartmontools.svn.sourceforge.net/svnroot/smartmontools/branches/unlabeled-1.76.2@721 4ea69e1a-61f1-4043-bf83-b5c94c648137 --- CVSROOT/checkoutlist | 13 - CVSROOT/commitinfo | 15 - CVSROOT/config | 14 - CVSROOT/cvswrappers | 23 - CVSROOT/editinfo | 21 - CVSROOT/loginfo | 28 - CVSROOT/modules | 26 - CVSROOT/notify | 12 - CVSROOT/rcsinfo | 13 - CVSROOT/taginfo | 20 - CVSROOT/verifymsg | 21 - sm5/CHANGELOG | 755 --------- sm5/COPYING | 340 ---- sm5/Makefile | 182 --- sm5/README | 263 ---- sm5/TODO | 73 - sm5/VERSION | 1 - sm5/WARNINGS | 16 - sm5/add | 8 - sm5/atacmds.c | 1530 ------------------ sm5/atacmds.cpp | 1530 ------------------ sm5/atacmds.h | 426 ----- sm5/ataprint.c | 1225 --------------- sm5/ataprint.cpp | 1225 --------------- sm5/ataprint.h | 70 - sm5/cvs-script | 6 - sm5/examplescripts/Example1 | 41 - sm5/examplescripts/Example2 | 21 - sm5/examplescripts/Example3 | 25 - sm5/examplescripts/README | 50 - sm5/extern.h | 82 - sm5/knowndrives.c | 412 ----- sm5/knowndrives.cpp | 412 ----- sm5/knowndrives.h | 82 - sm5/scsicmds.c | 1631 ------------------- sm5/scsicmds.cpp | 1631 ------------------- sm5/scsicmds.h | 299 ---- sm5/scsiprint.c | 707 --------- sm5/scsiprint.cpp | 707 --------- sm5/scsiprint.h | 40 - sm5/smartctl.8 | 890 ----------- sm5/smartctl.c | 714 --------- sm5/smartctl.h | 72 - sm5/smartd.8 | 1248 --------------- sm5/smartd.c | 2180 -------------------------- sm5/smartd.conf | 65 - sm5/smartd.conf.5 | 867 ---------- sm5/smartd.cpp | 2180 -------------------------- sm5/smartd.h | 179 --- sm5/smartd.initd | 55 - sm5/smartmontools.spec | 727 --------- sm5/utility.c | 254 --- sm5/utility.cpp | 254 --- sm5/utility.h | 74 - www/cvs-script | 6 - www/examples/HITACHI_DK23BA-20-0.txt | 163 -- www/examples/IC35L120AVV207-0.txt | 67 - www/examples/IC35L120AVVA07-0-0.txt | 69 - www/examples/IC35L120AVVA07-0-1.txt | 67 - www/examples/MAXTOR-0.txt | 139 -- www/examples/MAXTOR-1.txt | 143 -- www/examples/MAXTOR-2.txt | 79 - www/examples/MAXTOR-3.txt | 67 - www/examples/MAXTOR-4.txt | 65 - www/examples/MAXTOR-6.txt | 156 -- www/examples/Maxtor-5.txt | 127 -- www/examples/TOSHIBA-0.txt | 73 - www/examples/TOSHIBA-MK6021GAS.txt | 74 - www/index.html | 467 ------ www/script | 24 - 70 files changed, 25541 deletions(-) delete mode 100644 CVSROOT/checkoutlist delete mode 100644 CVSROOT/commitinfo delete mode 100644 CVSROOT/config delete mode 100644 CVSROOT/cvswrappers delete mode 100644 CVSROOT/editinfo delete mode 100644 CVSROOT/loginfo delete mode 100644 CVSROOT/modules delete mode 100644 CVSROOT/notify delete mode 100644 CVSROOT/rcsinfo delete mode 100644 CVSROOT/taginfo delete mode 100644 CVSROOT/verifymsg delete mode 100644 sm5/CHANGELOG delete mode 100644 sm5/COPYING delete mode 100644 sm5/Makefile delete mode 100644 sm5/README delete mode 100644 sm5/TODO delete mode 100644 sm5/VERSION delete mode 100644 sm5/WARNINGS delete mode 100755 sm5/add delete mode 100644 sm5/atacmds.c delete mode 100644 sm5/atacmds.cpp delete mode 100644 sm5/atacmds.h delete mode 100644 sm5/ataprint.c delete mode 100644 sm5/ataprint.cpp delete mode 100644 sm5/ataprint.h delete mode 100755 sm5/cvs-script delete mode 100755 sm5/examplescripts/Example1 delete mode 100755 sm5/examplescripts/Example2 delete mode 100755 sm5/examplescripts/Example3 delete mode 100644 sm5/examplescripts/README delete mode 100644 sm5/extern.h delete mode 100644 sm5/knowndrives.c delete mode 100644 sm5/knowndrives.cpp delete mode 100644 sm5/knowndrives.h delete mode 100644 sm5/scsicmds.c delete mode 100644 sm5/scsicmds.cpp delete mode 100644 sm5/scsicmds.h delete mode 100644 sm5/scsiprint.c delete mode 100644 sm5/scsiprint.cpp delete mode 100644 sm5/scsiprint.h delete mode 100644 sm5/smartctl.8 delete mode 100644 sm5/smartctl.c delete mode 100644 sm5/smartctl.h delete mode 100644 sm5/smartd.8 delete mode 100644 sm5/smartd.c delete mode 100644 sm5/smartd.conf delete mode 100644 sm5/smartd.conf.5 delete mode 100644 sm5/smartd.cpp delete mode 100644 sm5/smartd.h delete mode 100755 sm5/smartd.initd delete mode 100644 sm5/smartmontools.spec delete mode 100644 sm5/utility.c delete mode 100644 sm5/utility.cpp delete mode 100644 sm5/utility.h delete mode 100755 www/cvs-script delete mode 100644 www/examples/HITACHI_DK23BA-20-0.txt delete mode 100644 www/examples/IC35L120AVV207-0.txt delete mode 100644 www/examples/IC35L120AVVA07-0-0.txt delete mode 100644 www/examples/IC35L120AVVA07-0-1.txt delete mode 100644 www/examples/MAXTOR-0.txt delete mode 100644 www/examples/MAXTOR-1.txt delete mode 100644 www/examples/MAXTOR-2.txt delete mode 100644 www/examples/MAXTOR-3.txt delete mode 100644 www/examples/MAXTOR-4.txt delete mode 100644 www/examples/MAXTOR-6.txt delete mode 100644 www/examples/Maxtor-5.txt delete mode 100644 www/examples/TOSHIBA-0.txt delete mode 100644 www/examples/TOSHIBA-MK6021GAS.txt delete mode 100644 www/index.html delete mode 100755 www/script diff --git a/CVSROOT/checkoutlist b/CVSROOT/checkoutlist deleted file mode 100644 index b04b3501f..000000000 --- a/CVSROOT/checkoutlist +++ /dev/null @@ -1,13 +0,0 @@ -# The "checkoutlist" file is used to support additional version controlled -# administrative files in $CVSROOT/CVSROOT, such as template files. -# -# The first entry on a line is a filename which will be checked out from -# the corresponding RCS file in the $CVSROOT/CVSROOT directory. -# The remainder of the line is an error message to use if the file cannot -# be checked out. -# -# File format: -# -# [<whitespace>]<filename><whitespace><error message><end-of-line> -# -# comment lines begin with '#' diff --git a/CVSROOT/commitinfo b/CVSROOT/commitinfo deleted file mode 100644 index b19e7b7a6..000000000 --- a/CVSROOT/commitinfo +++ /dev/null @@ -1,15 +0,0 @@ -# The "commitinfo" file is used to control pre-commit checks. -# The filter on the right is invoked with the repository and a list -# of files to check. A non-zero exit of the filter program will -# cause the commit to be aborted. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being committed to, relative -# to the $CVSROOT. For the first match that is found, then the remainder -# of the line is the name of the filter to run. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". diff --git a/CVSROOT/config b/CVSROOT/config deleted file mode 100644 index ff43ec005..000000000 --- a/CVSROOT/config +++ /dev/null @@ -1,14 +0,0 @@ -# Set this to "no" if pserver shouldn't check system users/passwords -#SystemAuth=no - -# Put CVS lock files in this directory rather than directly in the repository. -#LockDir=/var/lock/cvs - -# Set `TopLevelAdmin' to `yes' to create a CVS directory at the top -# level of the new working directory when using the `cvs checkout' -# command. -#TopLevelAdmin=no - -# Set `LogHistory' to `all' or `TOFEWGCMAR' to log all transactions to the -# history file, or a subset as needed (ie `TMAR' logs all write operations) -#LogHistory=TOFEWGCMAR diff --git a/CVSROOT/cvswrappers b/CVSROOT/cvswrappers deleted file mode 100644 index 0accaf1b1..000000000 --- a/CVSROOT/cvswrappers +++ /dev/null @@ -1,23 +0,0 @@ -# This file affects handling of files based on their names. -# -# The -t/-f options allow one to treat directories of files -# as a single file, or to transform a file in other ways on -# its way in and out of CVS. -# -# The -m option specifies whether CVS attempts to merge files. -# -# The -k option specifies keyword expansion (e.g. -kb for binary). -# -# Format of wrapper file ($CVSROOT/CVSROOT/cvswrappers or .cvswrappers) -# -# wildcard [option value][option value]... -# -# where option is one of -# -f from cvs filter value: path to filter -# -t to cvs filter value: path to filter -# -m update methodology value: MERGE or COPY -# -k expansion mode value: b, o, kkv, &c -# -# and value is a single-quote delimited value. -# For example: -#*.gif -k 'b' diff --git a/CVSROOT/editinfo b/CVSROOT/editinfo deleted file mode 100644 index d78886c15..000000000 --- a/CVSROOT/editinfo +++ /dev/null @@ -1,21 +0,0 @@ -# The "editinfo" file is used to allow verification of logging -# information. It works best when a template (as specified in the -# rcsinfo file) is provided for the logging procedure. Given a -# template with locations for, a bug-id number, a list of people who -# reviewed the code before it can be checked in, and an external -# process to catalog the differences that were code reviewed, the -# following test can be applied to the code: -# -# Making sure that the entered bug-id number is correct. -# Validating that the code that was reviewed is indeed the code being -# checked in (using the bug-id number or a seperate review -# number to identify this particular code set.). -# -# If any of the above test failed, then the commit would be aborted. -# -# Actions such as mailing a copy of the report to each reviewer are -# better handled by an entry in the loginfo file. -# -# One thing that should be noted is the the ALL keyword is not -# supported. There can be only one entry that matches a given -# repository. diff --git a/CVSROOT/loginfo b/CVSROOT/loginfo deleted file mode 100644 index f31e552dd..000000000 --- a/CVSROOT/loginfo +++ /dev/null @@ -1,28 +0,0 @@ -# The "loginfo" file controls where "cvs commit" log information -# is sent. The first entry on a line is a regular expression which must match -# the directory that the change is being made to, relative to the -# $CVSROOT. If a match is found, then the remainder of the line is a filter -# program that should expect log information on its standard input. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name ALL appears as a regular expression it is always used -# in addition to the first matching regex or DEFAULT. -# -# You may specify a format string as part of the -# filter. The string is composed of a `%' followed -# by a single format character, or followed by a set of format -# characters surrounded by `{' and `}' as separators. The format -# characters are: -# -# s = file name -# V = old version number (pre-checkin) -# v = new version number (post-checkin) -# -# For example: -#DEFAULT (echo ""; id; echo %s; date; cat) >> $CVSROOT/CVSROOT/commitlog -# or -#DEFAULT (echo ""; id; echo %{sVv}; date; cat) >> $CVSROOT/CVSROOT/commitlog -^sm5$ /cvsroot/sitedocs/CVSROOT/cvstools/syncmail -u %{sVv} smartmontools-cvs@lists.sourceforge.net -^www$ /cvsroot/sitedocs/CVSROOT/cvstools/syncmail -u %{sVv} ballen4705@users.sourceforge.net diff --git a/CVSROOT/modules b/CVSROOT/modules deleted file mode 100644 index cb9e9efc9..000000000 --- a/CVSROOT/modules +++ /dev/null @@ -1,26 +0,0 @@ -# Three different line formats are valid: -# key -a aliases... -# key [options] directory -# key [options] directory files... -# -# Where "options" are composed of: -# -i prog Run "prog" on "cvs commit" from top-level of module. -# -o prog Run "prog" on "cvs checkout" of module. -# -e prog Run "prog" on "cvs export" of module. -# -t prog Run "prog" on "cvs rtag" of module. -# -u prog Run "prog" on "cvs update" of module. -# -d dir Place module in directory "dir" instead of module name. -# -l Top-level directory only -- do not recurse. -# -# NOTE: If you change any of the "Run" options above, you'll have to -# release and re-checkout any working directories of these modules. -# -# And "directory" is a path to a directory relative to $CVSROOT. -# -# The "-a" option specifies an alias. An alias is interpreted as if -# everything on the right of the "-a" had been typed on the command line. -# -# You can encode a module within a module by using the special '&' -# character to interpose another module into the current module. This -# can be useful for creating a module that consists of many directories -# spread out over the entire source repository. diff --git a/CVSROOT/notify b/CVSROOT/notify deleted file mode 100644 index 34f0bc288..000000000 --- a/CVSROOT/notify +++ /dev/null @@ -1,12 +0,0 @@ -# The "notify" file controls where notifications from watches set by -# "cvs watch add" or "cvs edit" are sent. The first entry on a line is -# a regular expression which is tested against the directory that the -# change is being made to, relative to the $CVSROOT. If it matches, -# then the remainder of the line is a filter program that should contain -# one occurrence of %s for the user to notify, and information on its -# standard input. -# -# "ALL" or "DEFAULT" can be used in place of the regular expression. -# -# For example: -#ALL mail %s -s "CVS notification" diff --git a/CVSROOT/rcsinfo b/CVSROOT/rcsinfo deleted file mode 100644 index 49e59f4d0..000000000 --- a/CVSROOT/rcsinfo +++ /dev/null @@ -1,13 +0,0 @@ -# The "rcsinfo" file is used to control templates with which the editor -# is invoked on commit and import. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being made to, relative to the -# $CVSROOT. For the first match that is found, then the remainder of the -# line is the name of the file that contains the template. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". diff --git a/CVSROOT/taginfo b/CVSROOT/taginfo deleted file mode 100644 index 274a46dd5..000000000 --- a/CVSROOT/taginfo +++ /dev/null @@ -1,20 +0,0 @@ -# The "taginfo" file is used to control pre-tag checks. -# The filter on the right is invoked with the following arguments: -# -# $1 -- tagname -# $2 -- operation "add" for tag, "mov" for tag -F, and "del" for tag -d -# $3 -- repository -# $4-> file revision [file revision ...] -# -# A non-zero exit of the filter program will cause the tag to be aborted. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being committed to, relative -# to the $CVSROOT. For the first match that is found, then the remainder -# of the line is the name of the filter to run. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". diff --git a/CVSROOT/verifymsg b/CVSROOT/verifymsg deleted file mode 100644 index 86f747ce2..000000000 --- a/CVSROOT/verifymsg +++ /dev/null @@ -1,21 +0,0 @@ -# The "verifymsg" file is used to allow verification of logging -# information. It works best when a template (as specified in the -# rcsinfo file) is provided for the logging procedure. Given a -# template with locations for, a bug-id number, a list of people who -# reviewed the code before it can be checked in, and an external -# process to catalog the differences that were code reviewed, the -# following test can be applied to the code: -# -# Making sure that the entered bug-id number is correct. -# Validating that the code that was reviewed is indeed the code being -# checked in (using the bug-id number or a seperate review -# number to identify this particular code set.). -# -# If any of the above test failed, then the commit would be aborted. -# -# Actions such as mailing a copy of the report to each reviewer are -# better handled by an entry in the loginfo file. -# -# One thing that should be noted is the the ALL keyword is not -# supported. There can be only one entry that matches a given -# repository. diff --git a/sm5/CHANGELOG b/sm5/CHANGELOG deleted file mode 100644 index e5b31072c..000000000 --- a/sm5/CHANGELOG +++ /dev/null @@ -1,755 +0,0 @@ -CHANGELOG for smartmontools - -$Id: CHANGELOG,v 1.133 2003/04/30 10:16:03 makisara Exp $ - -Copyright (C) 2002-3 Bruce Allen <smartmontools-support@lists.sourceforge.net> - -Home page of code is: http://smartmontools.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 the Free -Software Foundation; either version 2, or (at your option) any later -version. - -You should have received a copy of the GNU General Public License (for -example COPYING); if not, write to the Free Software Foundation, Inc., 675 -Mass Ave, Cambridge, MA 02139, USA. - -This code was originally developed as a Senior Thesis by Michael Cornwell -at the Concurrent Systems Laboratory (now part of the Storage Systems -Research Center), Jack Baskin School of Engineering, University of -California, Santa Cruz. http://ssrc.soe.ucsc.edu/ - -Maintainers/Developers Key: -[BA] Bruce Allen <smartmontools-support@lists.sourceforge.net> -[EB] Erik Inge Bols� <knan@mo.himolde.no> -[SB] Stanislav Brabec <sbrabec@suse.cz> -[PC] Peter Cassidy <pcassidy@mac.com> -[FM] Frederic L. W. Meunier <0@pervalidus.net> -[PW] Phil Williams <phil@subbacultcha.demon.co.uk> -[DG] Douglas Gilbert <dougg@torque.net> -[GG] Guido Guenther <agx@sigxcpu.org> -[KM] Kai M�kisara <kai.makisara@kolumbus.fi> - -NOTES FOR FUTURE RELEASES: see TODO file. - -CURRENT DEVELOPMENT VERSION (see VERSION file in this directory): - - <ADDITIONS TO THE CHANGE LOG SHOULD BE ADDED HERE, PLEASE> - [KM] More TapeAlert work. Added translations for media changer - alerts. TapeAlert support reported according to the log page - presence. ModeSense not attempted for non-ready tapes (all - drives do not support this after all). Get peripheral type from - Inquiry even if drive info is not printed. Add QUIETON() - QUIETOFF() to TapeAlert log check. - - [BA] Stupid bug in atacmds.c minor_str[] affected ataVersionInfo(). - Two missing commas meant that minor_str[] had two few elements, - leading to output like this: - Device Model: Maxtor 6Y120L0 - Serial Number: Y40BF74E - Firmware Version: YAR41VW0 - Device is: Not in smartctl database [for details use: -P showall] - ATA Version is: 7 - ATA Standard is: 9,minutes - ^^^^^^^^^ - Missing commas inserted. - - [BA] Fixed smartd bug. On device registration, if ATA device did - not support SMART error or self-test logs but user had asked to - monitor them, an attempt would be made to read them anyway, - possibly generating "Drive Seek" errors. We now check that - the self-test and error logs are supported before trying to - access them the first time. - - [GG/BA] Fixed bug where if SMART ATA error log not supported, - command was tried anyway. Changed some error printing to use - print handlers. - - [GG] Makefile modifications to ease packaging - - [DG] Did work for TapeAlerts (SCSI). Now can detect /dev/nst0 as a - SCSI device. Also open SCSI devices O_NONBLOCK so they don't - hang on open awaiting media. The ATA side should worry about - this also: during a DEVICESCAN a cd/dvd device without media - will hang. Added some TapeAlert code suggested by Kai Makisara. - -smartmontools-5.1-10 - - [PW] Extended the -F option/Directive to potentially fix other firmware - bugs in addition to the Samsung byte-order bug. Long option name is - now --firmwarebug and the option/Directive accepts an argument - indicating the type of firmware bug to fix. - - [BA] Fixed a bug that prevented the enable automatic off-line - test feature from enabling. It also prevented the enable Attribute - autosave from working. See CVS entry for additional details. - - [PW] Modified the -r/--report option (smartctl and smartd) to allow the - user to specify the debug level as a positive integer. - - [BA] Added --log directory option to smartctl. If the disk - supports the general-purpose logging feature set (ATA-6/7) - then this option enables the Log Directory to be printed. - This Log Directory shows which device logs are available, and - their lengths in sectors. - - [PW] Added -P/--presets option to smartctl and -P Directive to smartd. - - [GG] Introduce different exit codes indicating the type of problem - encountered for smartd. - - [DG] Add non-medium error count to '-l error' and extended self test - duration to '-l selftest'. Get scsi IEs and temperature changes - working in smartd. Step over various scsi disk problems rather - than abort smartd startup. - - [DG] Support -l error for SCSI disks (and tapes). Output error counter - log pages. - - [BA] Added -F/--fixbyteorder option to smartctl. This allows us to read - SMART data from some disks that have byte-reversed two- and four- - byte quantities in their SMART data structures. - - [BA] Fixed serious bug: the -v options in smartd.conf were all put - together and used together, not drive-by-drive. - - [PW] Added knowndrives.h and knowndrives.c. The knowndrives array - supersedes the drivewarnings array. - - [GG] add {-p,--pidfile} option to smartd to write a PID file on - startup. Update the manpage accordingly. - - [DG] Fix scsi smartd problem detecting SMART support. More cleaning - and fix (and rename) scsiTestUnitReady(). More scsi renaming. - - [BA] Fixed smartd so that if a disk that is explictily listed is not - found, then smartd will exit with nonzero status BEFORE forking. - If a disk can't be registered, this will also be detected before - forking, so that init scripts can react correctly. - - [BA] Replaced all linux-specific ioctl() calls in atacmds.c with - a generic handler smartcommandhandler(). Now the only routine - that needs to be implemented for a given OS is os_specific_handler(). - Also implemented the --report ataioctl. This provides - two levels of reporting. Using the option once gives a summary - report of device IOCTL transactions. Using the option twice give - additional info (a printout of ALL device raw 512 byte SMART - data structures). This is useful for debugging. - - [DG] more scsi cleanup. Output scsi device serial number (VPD page - 0x80) if available as part of '-i'. Implement '-t offline' as - default self test (only self test older disks support). - - [BA] Changed crit to info in loglevel of smartd complaint to syslog - if DEVICESCAN enabled and device not found. - - [BA] Added -v 194,10xCelsius option/Directive. Raw Attribute number - 194 is ten times the disk temperature in Celsius. - - [DG] scsicmds.[hc] + scsiprint.c: clean up indentation, remove tabs. - Introduce new intermediate interface based on "struct scsi_cmnd_io" - to isolate SCSI generic commands + responses from Linux details; - should help port to FreeBSD of SCSI part of smartmontools. - Make SCSI command builders more parametric. - -smartmontools-5.1-9 - - [BA] smartctl: if HDIO_DRIVE_TASK ioctl() is not implemented (no - kernel support, then try to assess drive health by examining - Attribute values/thresholds directly. - - [BA] smartd/smartctl: added -v 200,writeerrorcount option/Directive - for Fujitsu disks. - - [BA] smartd: Now send email if any of the SMART commands fails, - or if open()ing the device fails. This is often noted - as a common disk failure mode. - - [BA] smartd/smartctl: Added -v N,raw8 -v N,raw16 and -v N,raw48 - Directives/Options for printing Raw Attributes in different - Formats. - - [BA] smartd: Added -r ID and -R ID for reporting/tracking Raw - values of Attributes. - - [BA] smartd/smartctl: Changed printing of spin-up-time attribute - raw value to reflect current/average as per IBM standard. - - [BA] smartd/smartctl: Added -v 9,seconds option for disks which - use Attribute 9 for power-on lifetime in seconds. - - [BA] smartctl: Added a warning message so that users of some IBM - disks are warned to update their firmware. Note: we may want - to add a command-line flag to disable the warning messages. - I have done this in a general way, using regexp, so that we - can add warnings about any type of disk that we wish... - -smartmontools-5.1-7 - - [BA] smartd: Created a subdirectory examplescripts/ of source - directory that contains executable scripts for the -M exec PATH - Directive of smartd. - -smartmontools-5.1-5 - - [BA] smartd: DEVICESCAN in /etc/smartd.conf - can now be followed by all the same Directives as a regular - device name like /dev/hda takes. This allows one to use - (for example): - DEVICESCAN -m root@yoyodyne.com - in the /etc/smartd.conf file. - - [BA] smartd: Added -c (--checkonce) command-line option. This checks - all devices once, then exits. The exit status can be - used to learn if devices were detected, and if smartd is - functioning correctly. This is primarily for Distribution - scripters. - - [BA] smartd: Implemented -M exec Directive for - smartd.conf. This makes it possible to run an - arbitrary script or mailing program with the - -m option. - - [PW] smartd: Modified -M Directive so that it can be given - multiple times. Added -M exec Directive. - -smartmontools-5.1-4 - - [BA] Fixed bug in smartctl pointed out by Pierre Gentile. - -d scsi didn't work because tryata and tryscsi were - reversed -- now works on /devfs SCSI devices. - - [BA] Fixed bug in smartctl pointed out by Gregory Goddard - <ggoddard@ufl.edu>. Manual says that bit 6 of return - value turned on if errors found in smart error log. But - this wasn't implemented. - -smartmontools-5.1-3 - - [BA] Modified printing format for 9,minutes to read - Xh+Ym not X h + Y m, so that fields are fixed width. - - [BA] Added Attribute 240 "head flying hours" - -smartmontools-5.1.1 - - [BA] As requested, local time/date now printed by smartctl -i - - [PW] Added "help" argument to -v for smartctl - - [PW] Added -D, --showdirectives option to smartd - - [DG] add '-l selftest' capability for SCSI devices (update smartctl.8) - - [BA] smartd,smartctl: added additional Attribute modification option - -v 220,temp and -v 9,temp. - - [PW] Renamed smartd option -X to -d - -START OF SMARTMONTOOLS 5.1 series - -smartmontools-5.0.50 - - [PW] Changed smartd.conf Directives -- see man page - - [BA/DG] Fixed uncommented comment in smartd.conf - - [DG] Correct 'Recommended start stop count' for SCSI devices - - [PW] Replaced smartd.conf directive -C with smartd option -i - - [PW] Changed options for smartctl -- see man page. - - [BA] Use strerror() to generate system call error messages. - - [BA] smartd: fflush() all open streams before fork(). - - [BA] smartctl, smartd simplified internal handling of checksums - for simpler porting and less code. - -smartmontools-5.0.49 - - [PW] smartd --debugmode changed to --debug - - [BA] smartd/smartctl added attribute 230 Head Amplitude from - IBM DPTA-353750. - - [PW] Added list of proposed new options for smartctl to README. - - [PW] smartd: ParseOpts() now uses getopt_long() if HAVE_GETOPT_LONG is - defined and uses getopt() otherwise. This is controlled by CPPFLAGS in - the Makefile. - - [BA] smartd: Fixed a couple of error messages done with perror() - to redirect them as needed. - -smartmontools-5.0.48 - - [BA] smartctl: The -O option to enable an Immediate off-line test - did not print out the correct time that the test would take to - complete. This is because the test timer is volatile and not - fixed. This has been fixed, and the smartctl.8 man page has been - updated to explain how to track the Immediate offline test as it - progresses, and to further emphasize the differences between the - off-line immediate test and the self-tests. - - [BA] smartd/smartctl: Added new attribute (200) Multi_Zone_Error_Rate - - [BA] smartctl: modified so that arguments could have either a single - - as in -ea or multiple ones as in -e -a. Improved warning message for - device not opened, and fixed error in redirection of error output of - HD identity command. - - [PW] smartd: added support for long options. All short options are still - supported; see manpage for available long options. - - [BA] smartctl. When raw Attribute value was 2^31 or larger, did - not print correctly. - -smartmontools-5.0.46 - - [BA] smartd: added smartd.conf Directives -T and -s. The -T Directive - enables/disables Automatic Offline Testing. The -s Directive - enables/disables Attribute Autosave. Documentation and - example configuration file updated to agree. - - [BA] smartd: user can make smartd check the disks at any time - (ie, interrupt sleep) by sending signal SIGUSR1 to smartd. This - can be done for example with: - kill -USR1 <pid> - where <pid> is the process ID number of smartd. - - [EB] scsi: don't trust the data we receive from the drive too - much. It very well might have errors (like zero response length). - Seen on Megaraid logical drive, and verified in the driver source. - - [BA] smartd: added Directive -m for sending test email and - for modifying email reminder behavior. Updated manual, and sample - configuration file to illustrate & explain this. - - [BA] smartd: increased size of a continued smartd.conf line to - 1023 characters. - - [BA] Simplified Directive parsers and improved warning/error - messages. - -smartmontools-5.0.45 - - [EB] Fixed bug in smartd where testunitready logic inverted - prevented functioning on scsi devices. - The bug in question only affects smartd users with scsi devices. - To see if your version of smartd has the testunitready() bug, do - smartd -V - If the version of the module smartd.c in a line like: - Module: smartd.c revision: 1.66 date: 2002/11/17 - has a revision greater than or equal to 1.30, and less than or equal to - 1.64, then your version of the code has this problem. - This problem affected releases starting with RELEASE_5_0_16 up to and - including RELEASE_5_0_43. - - [BA] Added testunitnotready to smartctl for symmetry with smartd. - - [SB] added Czech descriptions to .spec file - [SB] corrected comment in smartd.conf example - - [BA] Changed way that entries in the ATA error log are printed, - to make it clearer which is the most recent error and - which is the oldest one. - - NOTE: All changes made prior to this point were done by Bruce Allen - [BA] although several of them had been suggested by earlier postings - by Stanislav Brabec [SB]. - -smartmontools-5.0.43 - - Changed Temperature_Centigrade to Temperature_Celsius. - The term "Centigrade" ceased to exist in 1948. (c.f - http://www.bartleby.com/64/C004/016.html). - -smartmontools-5.0.42 - - Modified SCSI device check to also send warning emails if - requested in directives file. - - Added a new smartd configuration file Directive: -M ADDRESS. - This sends a single warning email to ADDRESS for failures or - errors detected with the -c, -L, -l, or -f Directives. - -smartmontools-5.0.38 - - Modified perror() statements in atacmds.c so that printout for SMART - commands errors is properly suppressed or queued depending upon users - choices for error reporting modes. - - Added Italian descriptions to smartmontools.spec file. - - Started impementing send-mail-on-error for smartd; not yet enabled. - - Added -P (Permissive) Directive to smartd.conf file to allow SMART - monitoring of pre-ATA-3 Rev 4 disks that have SMART but do not have - a SMART capability bit. - - Removed charset encodings from smartmontools.spec file for non-English - fields. - -smartmontools-5.0.32 - - Added manual page smartd.conf.5 for configuration file. - - smartctl: Missing ANSI prototype in failuretest(); fixed. - - smartctl: Checksum warnings now printed on stdout, or are silent, - depending upon -q and -Q settings. - -smartmontools-5.0.31 - - Changed Makefile so that the -V option does not reflect file state - before commit! - - smartctl: added new options -W, -U, and -P to control if and how the - smartctl exits if an error is detected in either a SMART data - structure checksum, or a SMART command returns an error. - - modified manual page to break options into slightly more logical - categories. - - reformatted 'usage' message order to agree with man page ordering - - modified .spec file so that locale information now contains - character set definition. Changed pt_BR to pt since we do not use any - aspect other than language. See man setlocale. - -smartmontools-5.0.30 - smartctl: added new options -n and -N to force device to be ATA or SCSI - smartctl: no longer dies silently if device path does not start/dev/X - smartctl: now handles arbitrary device paths - -smartmontools-5.0.29 - Modified .spec file and Makefile to make them more compliant with - the "right" way of doing things. - -smartmontools-5.0.26 - Fixed typesetting error in man page smartd.8 - - Removed redundant variable (harmless) from smartd.c - -smartmontools-5.0.25 - - Added a new directive for the configuration file. If the word - DEVICESCAN appears before any non-commented material in the - configuration file, then the confi file will be ignored and the - devices wil be scanned. - -smartmontools-5.0.24 - - Note: it has now been confirmed that the code modifications between - 5.0.23 and 5.0.24 have eliminated the GCC 3.2 problems. Note that - there is a GCC bug howerver, see #848 at - http://gcc.gnu.org/cgi-bin/gnatsweb.pl?database=gcc&cmd=query - - Added new Directive for Configuration file: --C <N> This sets the time in between disk checks to be <N> - seconds apart. Note that although you can give - this Directive multiple times on different lines of - the configuration file, only the final value that - is given has an effect, and applies to all the - disks. The default value of <N> is 1800 sec, and - the minimum allowed value is ten seconds. - - Problem wasn't the print format. F.L.W. Meunier <0@pervalidus.net> - sent me a gcc 3.2 build and I ran it under a debugger. The - problem seems to be with passing the very large (2x512+4) byte - data structures as arguments. I never liked this anyway; it was - inherited from smartsuite. So I've changed all the heavyweight - functions (ATA ones, anyone) to just passing pointers, not hideous - kB size structures on the stack. Hopefully this will now build OK - under gcc 3.2 with any sensible compilation options. - -smartmontools-5.0.23 - - Because of reported problems with GCC 3.2 compile, I have gone - thorough the code and explicitly changed all print format - parameters to correspond EXACTLY to int unless they have to be - promoted to long longs. To quote from the glibc bible: [From - GLIBC Manual: Since the prototype doesn't specify types for - optional arguments, in a call to a variadic function the default - argument promotions are performed on the optional argument - values. This means the objects of type char or short int (whether - signed or not) are promoted to either int or unsigned int, as - appropriate.] - -smartmontools-5.0.22 - - smartd, smartctl now warn if they find an attribute whose ID - number does not match between Data and Threshold structures. - - Fixed nasty bug which led to wrong number of arguments for a - varargs statement, with attendent stack corruption. Sheesh! - Have added script to CVS attic to help find such nasties in the - future. - -smartmontools-5.0.21 - - Eliminated some global variables out of header files and other - minor cleanup of smartd. - -smartmontools-5.0.20 - - Did some revision of the man page for smartd and made the usage - messages for Directives 100% consistent. - -smartmontools-5.0-19 - - smartd: prints warning message when it gets SIGHUP, saying that it - is NOT re-reading the config file. - - smartctl: updated man page to say self-test commands -O,x,X,s,S,A - appear to be supported in the code. [I can't test these, can anyone - report?] - -smartmontools-5.0-18 - - smartctl: smartctl would previously print the LBA of a self-test - if it completed, and the LBA was not 0 or 0xff...f However - according to the specs this is not correct. According to the - specs, if the self-test completed without error then LBA is - undefined. This version fixes that. LBA value only printed if - self-test encountered an error. - -smartmontools-5.0-17 - - smartd has changed significantly. This is the first CVS checkin of - code that extends the options available for smartd. The following - options can be placed into the /etc/smartd.conf file, and control the - behavior of smartd. - Configuration file Directives (following device name): - -A Device is an ATA device - -S Device is a SCSI device - -c Monitor SMART Health Status - -l Monitor SMART Error Log for changes - -L Monitor SMART Self-Test Log for new errors - -f Monitor for failure of any 'Usage' Attributes - -p Report changes in 'Prefailure' Attributes - -u Report changes in 'Usage' Attributes - -t Equivalent to -p and -u Directives - -a Equivalent to -c -l -L -f -t Directives - -i ID Ignore Attribute ID for -f Directive - -I ID Ignore Attribute ID for -p, -u or -t Directive - # Comment: text after a hash sign is ignored - \ Line continuation character - - cleaned up functions used for printing CVS IDs. Now use string - library, as it should be. - - modified length of device name string in smartd internal structure - to accomodate max length device name strings - - removed un-implemented (-e = Email notification) option from - command line arg list. We'll put it back on when implemeneted. - - smartd now logs serious (fatal) conditions in its operation at - loglevel LOG_CRIT rather than LOG_INFO before exiting with error. - - smartd used to open a file descriptor for each SMART enabled - device, and then keep it open the entire time smartd was running. - This meant that some commands, like IOREADBLKPART did not work, - since the fd to the device was open. smartd now opens the device - when it needs to read values, then closes it. Also, if one time - around it can't open the device, it simply prints a warning - message but does not give up. Have eliminated the .fd field from - data structures -- no longer gets used. - - smartd now opens SCSI devices as well using O_RDONLY rather than - O_RDWR. If someone can no longer monitor a SCSI device that used - to be readable, this may well be the reason why. - - smartd never checked if the number of ata or scsi devices detected - was greater than the max number it could monitor. Now it does. - -smartmontools-5.0-16 - - smartd on startup now looks in the configuration file /etc/smartd.conf for - a list of devices which to include in its monitoring list. See man page - (man smartd) for syntax. - - smartd: close file descriptors of SCSI device if not SMART capable - Closes ALL file descriptors after forking to daemon. - - added new temperature attribute (231, temperature) - - smartd: now open ATA disks using O_RDONLY - -smartmontools-5.0-11 - - smartd now prints the name of a failed or changed attribute - into logfile, not just ID number - - Changed name of -p (print version) option to -V - - Minor change in philosophy: if a SMART command fails or the device - appears incapable of a SMART command that the user has asked for, - complain by printing an error message, but go ahead and try - anyway. Since unimplemented SMART commands should just return an - error but not cause disk problems, this should't cause any - difficulty. - - Added two new flags: q and Q. q is quiet mode - only print: For - the -l option, errors recorded in the SMART error log; For the -L - option, errors recorded in the device self-test log; For the -c - SMART "disk failing" status or device attributes (pre-failure or - usage) which failed either now or in the past; For the -v option - device attributes (pre-failure or usage) which failed either now - or in the past. Q is Very Quiet mode: Print no ouput. The only - way to learn about what was found is to use the exit status of - smartctl. - - smartctl now returns sensible values (bitmask). See smartctl.h - for the values, and the man page for documentation. - - The SMART status check now uses the correct ATA call. If failure - is detected we search through attributes to list the failed ones. - If the SMART status check shows GOOD, we then look to see if their - are any usage attributes or prefail attributes have failed at any - time. If so we print them. - - Modified function that prints vendor attributes to say if the - attribute has currently failed or has ever failed. - - -p option now prints out license info and CVS strings for all - modules in the code, nicely formatted. - - Previous versions of this code (and Smartsuite) only generate - SMART failure errors if the value of an attribute is below the - threshold and the prefailure bit is set. However the ATA Spec - (ATA4 <=Rev 4) says that it is a SMART failure if the value of an - attribute is LESS THAN OR EQUAL to the threshold and the - prefailure bit is set. This is now fixed in both smartctl and - smartd. Note that this is a troubled subject -- the original - SFF 8035i specification defining SMART was inconsistent about - this. One section says that Attribute==Threshold is pass, - and another section says it is fail. However the ATA specs are - consistent and say Attribute==Threshold is a fail. - - smartd did not print the correct value of any failing SMART attribute. It - printed the index in the attribute table, not the attribute - ID. This is fixed. - - when starting self-tests in captive mode ioctl returns EIO because - the drive has been busied out. Detect this and don't return an eror - in this case. Check this this is correct (or how to fix it?) - - fixed possible error in how to determine ATA standard support - for devices with no ATA minor revision number. - - device opened only in read-only not read-write mode. Don't need R/W - access to get smart data. Check this with Andre. - - smartctl now handles all possible choices of "multiple options" - gracefully. It goes through the following phases of operation, - in order: INFORMATION, ENABLE/DISABLE, DISPLAY DATA, RUN/ABORT TESTS. - Documentation has bee updated to explain the different phases of - operation. Control flow through ataPrintMain() - simplified. - - If reading device identity information fails, try seeing if the info - can be accessed using a "DEVICE PACKET" command. This way we can - at least get device info. - - Modified Makefile to automatically tag CVS archive on issuance of - a release - - Modified drive detection so minor device ID code showing ATA-3 rev - 0 (no SMART) is known to not be SMART capable. - - Now verify the checksum of the device ID data structure, and of the - attributes threshold structure. Before neither of these - structures had their checksums verified. - - New behavior vis-a-vis checksums. If they are wrong, we log - warning messages to stdout, stderr, and syslog, but carry on - anyway. All functions now call a checksumwarning routine if the - checksum doesn't vanish as it should. - - Changed Read Hard Disk Identity function to get fresh info from - the disk on each call rather than to use the values that were read - upon boot-up into the BIOS. This is the biggest change in this - release. The ioctl(device, HDIO_GET_IDENTITY, buf ) call should - be avoided in such code. Note that if people get garbled strings - for the model, serial no and firmware versions of their drives, - then blame goes here (the BIOS does the byte swapping for you, - apparently!) - - Function ataSmartSupport now looks at correct bits in drive - identity structure to verify first that these bits are valid, - before using them. - - Function ataIsSmartEnabled() written which uses the Drive ID state - information to tell if SMART is enabled or not. We'll carry this - along for the moment without using it. - - Function ataDoesSmartWork() guaranteed to work if the device - supports SMART. - - Replace some numbers by #define MACROS - - Wrote Function TestTime to return test time associated with each - different type of test. - - Thinking of the future, have added a new function called - ataSmartStatus2(). Eventually when I understand how to use the - TASKFILE API and am sure that this works correctly, it will - replace ataSmartStatus(). This queries the drive directly to - see if the SMART status is OK, rather than comparing thresholds to - attribute values ourselves. But I need to get some drives that fail - their SMART status to check it. - - -smartmontools-5.0-10 - Removed extraneous space before printing in some error messages - Fixed additional typos in documentation - Fixed some character buffers that were too short for their contents. - -smartmontools-5.0-9 - - Put project home path into all source files near the top - Corrected typos in the documentation - Modified Makefile so that Mandrake Cooker won't increment version number - (unless they happen to be working on my machine, which I doubt!) - -smartmontools-5.0-8: - - For IBM disks whose raw temp data includes three temps. print all - three - - print timestamps for error log to msec precision - - added -m option for Hitachi disks that store power on life in - minutes - - added -L option for printing self-test error logs - - in -l option, now print power on lifetime, so that one can see - when the error took place - - updated SMART structure definitions to ATA-5 spec - - added -p option - - added -f and -F options to enable/disable autosave threshold - parameters - - changed argv parsing to use getops -- elminate buffer overflow - vulnerability - - expanded and corrected documentation - - fixed problem with smartd. It did not actually call - ataSmartEnable()! Since the argument was left out, the test - always suceeded because it evaluated to a pointer to the function. - - smartd: closed open file descriptors if device does not support - smart. Note: this still needs to be fixed for SCSI devices - - -smartmontools-5.0-0 STARTED with smartsuite-2.1-2 diff --git a/sm5/COPYING b/sm5/COPYING deleted file mode 100644 index 60549be51..000000000 --- a/sm5/COPYING +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - <one line to give the program's name and a brief idea of what it does.> - Copyright (C) 19yy <name of author> - - 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 Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) 19yy name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - <signature of Ty Coon>, 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/sm5/Makefile b/sm5/Makefile deleted file mode 100644 index cd000723a..000000000 --- a/sm5/Makefile +++ /dev/null @@ -1,182 +0,0 @@ -# Makefile for smartmontools -# -# Home page: http://smartmontools.sourceforge.net -# -# $Id: Makefile,v 1.65 2003/04/23 13:19:40 guidog Exp $ -# -# Copyright (C) 2002-3 Bruce Allen <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 the Free -# Software Foundation; either version 2, or (at your option) any later -# version. -# -# You should have received a copy of the GNU General Public License (for -# example COPYING); if not, write to the Free Software Foundation, Inc., 675 -# Mass Ave, Cambridge, MA 02139, USA. -# -# This code was originally developed as a Senior Thesis by Michael Cornwell -# at the Concurrent Systems Laboratory (now part of the Storage Systems -# Research Center), Jack Baskin School of Engineering, University of -# California, Santa Cruz. http://ssrc.soe.ucsc.edu/ - -CC = gcc - -# Debugging -# CFLAGS = -fsigned-char -Wall -g - -# Build against kernel header files. Change linux-2.4 to correct path for your system -# CFLAGS = -fsigned-char -Wall -O2 -I./usr/src/linux-2.4/include - -# Normal build NOTE: I have had reports that with gcc 3.2 this code -# fails if you use anything but -Os. I'll remove this comment when -# this is resolved, or I am reminded of it! GCC GNATS bug report -# #8404. If you are getting strange output from gcc 3.2 try -# uncommenting LDFLAGS -s below. Stripping the symbols seems to fix -# the problem. -CFLAGS = -fsigned-char -Wall -O2 -CPPFLAGS = -DHAVE_GETOPT_H -DHAVE_GETOPT_LONG -LDFLAGS = # -s - -GZIP=/bin/gzip -INSTALL = install -INSTALL_PROGRAM = ${INSTALL} -INSTALL_DATA = ${INSTALL} -m 644 - -releasefiles=atacmds.c atacmds.h ataprint.c ataprint.h CHANGELOG COPYING \ - extern.h knowndrives.c knowndrives.h Makefile README scsicmds.c scsicmds.h \ - scsiprint.c scsiprint.h smartctl.8 smartctl.c smartctl.h smartd.8 smartd.c \ - smartd.h smartd.initd TODO WARNINGS VERSION smartd.conf smartd.conf.5 \ - utility.c utility.h examplescripts/ - -counter=$(shell cat VERSION) -pkgname=smartmontools-5.1 -pkgname2=$(pkgname)-$(counter) - -docdir=/usr/share/doc/$(pkgname) -es=examplescripts -examplesdir=$(docdir)/$(es) - -all: smartd smartctl - @echo -e "\n\nSmartd can now use a configuration file /etc/smartd.conf. Do:\n\n\tman ./smartctl.8\n\tman ./smartd.8\n\tman ./smartd.conf.5\n" - @echo -e "to read the manual pages now. Unless you do a \"make install\" the manual pages won't be installed.\n" - -smartctl: smartctl.c atacmds.o ataprint.o scsicmds.o scsiprint.o utility.o knowndrives.o\ - smartctl.h atacmds.h ataprint.h scsicmds.h scsiprint.h \ - utility.h extern.h knowndrives.h VERSION Makefile - $(CC) -DSMARTMONTOOLS_VERSION=$(counter) -o smartctl $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) smartctl.c \ - atacmds.o ataprint.o knowndrives.o scsicmds.o scsiprint.o utility.o - -smartd: smartd.c atacmds.o ataprint.o scsicmds.o utility.o knowndrives.o \ - smartd.h atacmds.h ataprint.h knowndrives.h scsicmds.h utility.h extern.h VERSION \ - Makefile - $(CC) -DSMARTMONTOOLS_VERSION=$(counter) -o smartd $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) smartd.c \ - atacmds.o ataprint.o knowndrives.o scsicmds.o utility.o - -atacmds.o: atacmds.c atacmds.h utility.h extern.h Makefile - $(CC) $(CFLAGS) $(CPPFLAGS) -c atacmds.c - -ataprint.o: ataprint.c atacmds.h ataprint.h knowndrives.h smartctl.h extern.h utility.h \ - Makefile - $(CC) $(CFLAGS) $(CPPFLAGS) -c ataprint.c - -scsicmds.o: scsicmds.c scsicmds.h extern.h Makefile - $(CC) $(CFLAGS) $(CPPFLAGS) -c scsicmds.c - -scsiprint.o: scsiprint.c extern.h scsicmds.h scsiprint.h smartctl.h utility.h Makefile - $(CC) $(CFLAGS) $(CPPFLAGS) -c scsiprint.c - -utility.o: utility.c utility.h Makefile - $(CC) $(CFLAGS) $(CPPFLAGS) -c utility.c - -knowndrives.o: knowndrives.c knowndrives.h utility.h atacmds.h ataprint.h Makefile - $(CC) $(CFLAGS) $(CPPFLAGS) -c knowndrives.c - - - -# This extracts the configuration file directives from smartd.8 and -# inserts them into smartd.conf.5 -smartd.conf.5: smartd.8 - sed '1,/STARTINCLUDE/ D;/ENDINCLUDE/,$$D' < smartd.8 > tmp.directives - sed '/STARTINCLUDE/,$$D' < smartd.conf.5 > tmp.head - sed '1,/ENDINCLUDE/D' < smartd.conf.5 > tmp.tail - cat tmp.head > smartd.conf.5 - echo "\# STARTINCLUDE" >> smartd.conf.5 - cat tmp.directives >> smartd.conf.5 - echo "\# ENDINCLUDE" >> smartd.conf.5 - cat tmp.tail >> smartd.conf.5 - rm -f tmp.head tmp.tail tmp.directives -clean: - rm -f *.o smartctl smartd *~ \#*\# smartmontools*.tar.gz smartmontools*.rpm temp.* smart*.8.gz smart*.5.gz - -install: - if [ ! -f smartd -o ! -f smartctl ] ; then echo -e "\n\nYOU MUST FIRST DO \"make\"\n" ; exit 1 ; fi - $(GZIP) -c smartctl.8 > smartctl.8.gz - $(GZIP) -c smartd.8 > smartd.8.gz - $(GZIP) -c smartd.conf.5 > smartd.conf.5.gz - rm -f $(DESTDIR)/usr/share/man/man8/smartctl.8 - rm -f $(DESTDIR)/usr/share/man/man8/smartd.8 - $(INSTALL_PROGRAM) -D smartctl $(DESTDIR)/usr/sbin/smartctl - $(INSTALL_PROGRAM) -D smartd $(DESTDIR)/usr/sbin/smartd - $(INSTALL_PROGRAM) -D smartd.initd $(DESTDIR)/etc/rc.d/init.d/smartd - $(INSTALL_DATA) -D smartctl.8.gz $(DESTDIR)/usr/share/man/man8/smartctl.8.gz - $(INSTALL_DATA) -D smartd.8.gz $(DESTDIR)/usr/share/man/man8/smartd.8.gz - $(INSTALL_DATA) -D smartd.conf.5.gz $(DESTDIR)/usr/share/man/man5/smartd.conf.5.gz - $(INSTALL_DATA) -D CHANGELOG $(DESTDIR)/$(docdir)/CHANGELOG - $(INSTALL_DATA) -D COPYING $(DESTDIR)/$(docdir)/COPYING - $(INSTALL_DATA) -D README $(DESTDIR)/$(docdir)/README - $(INSTALL_DATA) -D TODO $(DESTDIR)/$(docdir)/TODO - $(INSTALL_DATA) -D VERSION $(DESTDIR)/$(docdir)/VERSION - $(INSTALL_DATA) -D WARNINGS $(DESTDIR)/$(docdir)/WARNINGS - $(INSTALL_DATA) -D smartd.conf $(DESTDIR)/$(docdir)/smartd.conf - $(INSTALL_DATA) -D $(es)/README $(DESTDIR)/$(docdir)/$(es)/README - $(INSTALL_PROGRAM) -D $(es)/Example1 $(DESTDIR)/$(examplesdir)/Example1 - $(INSTALL_PROGRAM) -D $(es)/Example2 $(DESTDIR)/$(examplesdir)/Example2 - $(INSTALL_PROGRAM) -D $(es)/Example3 $(DESTDIR)/$(examplesdir)/Example3 - if [ ! -f $(DESTDIR)/etc/smartd.conf ]; then \ - $(INSTALL_DATA) -D smartd.conf $(DESTDIR)/etc/smartd.conf; \ - else \ - $(INSTALL_DATA) -D smartd.conf $(DESTDIR)/etc/smartd.conf.example;\ - fi - @echo -e "\n\nTo manually start smartd on bootup, run /etc/rc.d/init.d/smartd start" - @echo "To automatically start smartd on bootup, run /sbin/chkconfig --add smartd" - @echo -e "\n\nSmartd can now use a configuration file /etc/smartd.conf. Do:\nman 8 smartd\n." - @echo -e "A sample configuration file may be found in ${docdir}.\n\n" - -# perhaps for consistency I should also have $(DESTDIR) for the uninstall... -uninstall: - rm -f /usr/share/man/man8/smartctl.8 /usr/share/man/man8/smartd.8 /usr/sbin/smartctl \ - /usr/share/man/man8/smartctl.8.gz /usr/share/man/man8/smartd.8.gz \ - /usr/share/man/man5/smartd.conf.5.gz /usr/sbin/smartd - rm -rf /usr/share/doc/smartmontools-5.1/ - if [ -f /var/lock/subsys/smartd -a -f /etc/rc.d/init.d/smartd ] ; then /etc/rc.d/init.d/smartd stop ; fi - if [ -f /etc/rc.d/init.d/smartd ] ; then /sbin/chkconfig --del smartd ; fi - if [ -f /etc/rc.d/init.d/smartd ] ; then rm -f /etc/rc.d/init.d/smartd ; fi - if [ -f /etc/smartd.conf.example ] ; then rm -f /etc/smartd.conf.example ; fi - if [ -f /etc/smartd.conf ] ; then echo -e "\n\nWe have NOT REMOVED /etc/smartd.conf\n\n" ; fi - - -# Some of this mess is to automatically increment the release numbers. -# The number of the next release is kept in the file "VERSION" -release: smartd.conf.5 - if [ ! -f add -o ! -d CVS ] ; then echo "The make release target requires files checked out of CVS" ; exit 1 ; fi - cat smartmontools.spec | sed '/Release:/d' > temp.spec - echo "Release: " $(counter) > temp.version - cat temp.version temp.spec > smartmontools.spec - rm -f temp.spec temp.version - . cvs-script && cvs commit -m "Release 5.1.$(counter)" - . cvs-script && cvs tag -d "RELEASE_5_1_$(counter)" && cvs tag "RELEASE_5_1_$(counter)" - rm -rf $(pkgname) - mkdir $(pkgname) - cp -a $(releasefiles) $(pkgname) - rm -rf $(pkgname)/examplescripts/CVS - tar zcvf $(pkgname).tar.gz $(pkgname) - mv -f $(pkgname) $(pkgname2) - tar zcvf $(pkgname2).tar.gz $(pkgname2) - rm -rf $(pkgname2) - mv -f $(pkgname).tar.gz /usr/src/redhat/SOURCES/ - rpm -ba smartmontools.spec - mv /usr/src/redhat/RPMS/i386/$(pkgname)*.rpm . - mv /usr/src/redhat/SRPMS/$(pkgname)*rpm . - rm -f /usr/src/redhat/SOURCES/$(pkgname).tar.gz - echo `hostname` | grep -q lap && echo $(shell ./add) > VERSION diff --git a/sm5/README b/sm5/README deleted file mode 100644 index 29ca307aa..000000000 --- a/sm5/README +++ /dev/null @@ -1,263 +0,0 @@ -=============================================== -SMARTMONTOOLS - SMART utility toolset for Linux -=============================================== - -== HOME == -The home for smartmontools is located at: - http://smartmontools.sourceforge.net -Please see this web site for updates, documentation, and for -submitting patches and bug reports. - -You will find a mailing list for support and other questions at: -http://lists.sourceforge.net/lists/listinfo/smartmontools-support - - -== COPYING == -Copyright (C) 2002-3 Bruce Allen <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 the Free -Software Foundation; either version 2, or (at your option) any later -version. - -You should have received a copy of the GNU General Public License (for -example COPYING); if not, write to the Free Software Foundation, Inc., 675 -Mass Ave, Cambridge, MA 02139, USA. - - -== CREDITS == -This code was originally developed as a Senior Thesis by Michael Cornwell -at the Concurrent Systems Laboratory (now part of the Storage Systems -Research Center), Jack Baskin School of Engineering, University of -California, Santa Cruz. http://ssrc.soe.ucsc.edu/ - - -== OVERVIEW == -SMARTMONTOOLS contains utilities that control and monitor storage -devices using the Self-Monitoring, Analysis and Reporting Technology -(S.M.A.R.T.) system build into ATA and SCSI Hard Drives. This is used -to check the reliability of the hard drive and to predict drive -failures. SMARTMONTOOLS Version 5.x is designed to comply to the -ATA/ATAPI-5 specification (Revision 1). Future releases of -SMARTMONTOOLS (Versions 6.x and 7.x) will comply with the ATA/ATAPI-6 -and ATA/ATAPI-7 specifications. - -This package is meant to be an up-to-date replacement for the -ucsc-smartsuite and smartsuite packages, and is derived from that -code. - - -== CONTENTS == -The suite contains two utilities: - -smartctl is a command line utility designed to perform - S.M.A.R.T. tasks.such as disk self-checks, and to - report the S.M.A.R.T. status of the disk. - -smartd is a daemon that periodically monitors S.M.A.R.T. status and - reports errors and changes in S.M.A.R.T. attributes to syslog. - -SEE THE FILE "WARNINGS" FOR REPORTS OF HARDWARE WHERE THESE UTILITIES MIGHT -CAUSE SERIOUS PROBLEMS SUCH AS LOCKUPS. - -If you have just downloaded smartmontools from the URL above, then -you can read about these commands using the man pages. Within this -directory the commands: - man ./smartctl.8 -and - man ./smartd.8 - -will display the manual pages for the two commands. If you have -already installed the package on your system, then: - man smartctl -and - man smartd -will display the same information. - - -== INSTALLATION == -To install, use the commands: - make - make install - -Any recent Linux distribution should support this package. Note that -smartmontools requires Linux kernel 2.2.14 or greater in order to run -at all. But to give the ATA RETURN SMART STATUS command, the kernel -needs to support the HDIO_DRIVE_TASK ioctl(). Any 2.4 series kernel -should provide this support. I am told that some of the 2.2.20 and -later kernels also provide this support if they are properly -patched/configured. - -Seventeen files are installed: -/usr/sbin/smartd [Executable daemon] -/usr/sbin/smartctl [Executable command-line utility] -/etc/rc.d/init.d/smartd [Init/Startup script for smartd] -/usr/share/man/man8/smartctl.8.gz [Manual page] -/usr/share/man/man8/smartd.8.gz [Manual page] -/usr/share/man/man5/smartd.conf.5.gz [Manual page] -/usr/share/doc/smartmontools-5.1/README [What you are reading!] -/usr/share/doc/smartmontools-5.1/TODO [Things that need to be done/fixed] -/usr/share/doc/smartmontools-5.1/CHANGELOG [A log of changes. Also see CVS] -/usr/share/doc/smartmontools-5.1/COPYING [GNU Public License.] -/usr/share/doc/smartmontools-5.1/VERSION [Version number] -/usr/share/doc/smartmontools-5.1/WARNINGS [Systems where lockups or other serious problems reported] -/usr/share/doc/smartmontools-5.1/smartd.conf [Example Configuration file for /etc/] -/usr/share/doc/smartmontools-5.1/examplescripts [Executable scripts for -M exec of smartd.conf (4 files)] - -Source and binary RPM files are available at the website listed above. - -PLEASE READ THE MANUAL PAGES FOR SMARTCTL AND SMARTD FOR MORE INFORMATION. - - -STARTING WITH SMARTMONTOOLS 5.1.X, THE COMMAND LINE OPTIONS AND THE -SMARTD.CONF DIRECTIVES HAVE BEEN RENAMED. WHAT FOLLOWS IS A SUMMARY -TABLE SHOWING THE COMPARISON BETWEEN THE OLD AND THE NEW OPTION AND -DIRECTIVE NAMES. - -== NEW OPTION NAMES FOR SMARTCTL 5.1 == -The following is a synopsis of the new options in smartctl 5.1 -- please see the -man pages for more information. - - -h, --help, --usage - Show usage and syntax help - - -V, --version, --copyright, --license - Show version, copyright, and license info then exit - - -q MODE, --quietmode=MODE - Set the quiet mode to one of: errorsonly, silent - - -d TYPE, --device=TYPE - Set the device type to one of: ata, scsi - - -T TYPE, --tolerance=TYPE - Set tolerance level to one of: - normal - Exit if a mandatory SMART command fails [DEFAULT] - conservative - Exit if any SMART command fails - permissive - Continue even if a mandatory SMART command fails - - -b TYPE, --badsum=TYPE - Action to take on a bad checksum. TYPE and its meaning are: - warn - Issue a warning, but continue [DEFAULT] - exit - Exit smartctl - ignore - Continue silently without issuing a warning [NEW] - - -s VALUE, --smart=VALUE - Enable/disable SMART. VALUE is one of: on, off - - -o VALUE, --offlineauto=VALUE - Enable/disable automatic offline testing. VALUE is one of: on, off - - -S VALUE, --saveauto=VALUE - Enable/disable attribute autosave. VALUE is one of: on, off - - -H, --health - Show SMART health status - - -c, --capabilities - Show SMART capabilities - - -A, --attributes - Show SMART vendor-specific attributes and values. - - -l TYPE, --log=TYPE - Show device log. Type is one of: error, selftest - - -i, --info - Show drive information - - -a, --all - Show all SMART information. Equivalent to -HcAi -l error -l selftest - - -v N,OPTION , --vendorattribute=N,OPTION - Set vendor specific OPTION for attribute N. Currently supported are: - - N OPTION Effect - ----------------------------------------------------------- - 009 minutes Display in minutes instead of hours - - Note that in the future this option may be used multiple times - with different arguments, to modify options for different - attributes. - - -t TEST, --test=TEST - Perform TEST immediately. TEST is one of: offline, short, long - - -C, --captive - When used with -t, performs test in captive mode. Has no effect on - offline test, or when used without -t option. - - -X, --abort - Abort any non-captive test - -The following table shows the mapping of old to new smartctl options and of -old to new smartd.conf directives: - - ------------------------------------------------------------------------------------------------------------------- - smartctl smartctl options smartctl options smartd.conf smartd.conf - options Versions >= 5.1 Versions >= 5.1 DIRECTIVES DIRECTIVES - Versons<=5.0 (short options) (long options) Versions <= 5.0 Versions >= 5.1 - ------------------------------------------------------------------------------------------------------------------- - -h, -? -h, -? --help - -V -V --version, --copyright, --license - -i -i --info CONFLICT - -q -q errorsonly --quietmode=errorsonly - -Q -q silent --quietmode=silent - -n -d ata --device=ata -A -d ata - -N -d scsi --device=scsi -S -d scsi - -P -T permissive --tolerance=permissive -P -T permissive - -U -T conservative --tolerance=conservative - -W -b --badsum=exit - -r --report=TYPE - -e -s on --smart=on - -d -s off --smart=off - -t -o on --offlineauto=on -T 1 -o on - -T -o off --offlineauto=off -T 0 -o off - -f -S on --saveauto=on -s 1 -S on - -F -S off --saveauto=off -s 0 -S off - -c -H --health -c -H - -g -c --capabilities - -v -A --attributes -p, -u, -f, -t -p, -u, -t - -l -l error --log=error -l -l error - -L -l selftest --log=selftest -L -l selftest - -a -a --all -a -a - -m -v 9,minutes --vendorattribute=9,minutes - -O -t offline --test=offline - -S -t short --test=short - -s -t short -C --test=short --captive - -X -t long --test=long - -x -t long -C --test=long --captive - -A -X --abort - - - NOW A COMMAND-LINE OPTION (-i N, --interval N) =======> -C N Set checktime CMD LINE: -i N - -f usage attributes -f - -M ADD Email addresses -m ADD - -m -3 Email mode -M diminishing -M test - -m -2 Email mode -M daily -M test - -m -1 Email mode -M once -M test - If no -M is given, this is the DEFAULT =====> -m 0 Email mode -M once - -m 1 Email mode -M once - -m 2 Email mode -M daily - -m 3 Email mode -M diminishing - New feature (see man page) =====> -M exec SCRIPT - -i N Ignore -i N - -I N Ignore -I N - # Comment # - \ Line continuation \ - ------------------------------------------------------------------------------------------------------------------- - -Changes to smartd options: - - ---------------------------------------------------------------------------------------------------------- - 5.0 short 5.0 long 5.1 short 5.1 long - option option option option - ---------------------------------------------------------------------------------------------------------- - -h, -? --help -h, -? --help - -V --version, --copyright, --license -V --version, --copyright, --license - -X --debug -d --debug - -i N --interval=N - -D --showdirectives - -r --report=TYPE - ---------------------------------------------------------------------------------------------------------- - diff --git a/sm5/TODO b/sm5/TODO deleted file mode 100644 index 9b405e2dd..000000000 --- a/sm5/TODO +++ /dev/null @@ -1,73 +0,0 @@ -TODO list for smartmontools: - -Home page of code is: http://smartmontools.sourceforge.net - -Copyright (C) 2002-3 Bruce Allen <smartmontools-support@lists.sourceforge.net> - -$Id: TODO,v 1.36 2003/04/14 22:32:02 guidog Exp $ - -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 -Software Foundation; either version 2, or (at your option) any later -version. - -You should have received a copy of the GNU General Public License (for -example COPYING); if not, write to the Free Software Foundation, Inc., 675 -Mass Ave, Cambridge, MA 02139, USA. - -This code was originally developed as a Senior Thesis by Michael Cornwell -at the Concurrent Systems Laboratory (now part of the Storage Systems -Research Center), Jack Baskin School of Engineering, University of -California, Santa Cruz. http://ssrc.soe.ucsc.edu/. - - -Testing -------- -Test with SCSI, FireWire, USB, and SATA devices. Doug Gilbert is now -doing some of this. - -Extensions ----------- -Produce version for ATA/ATAPI-6 (support for extended error logs) - -Produce version for ATA/ATAPI-7 - - -smartctl: ---------- - -Handle extended error and self-test logs gracefully. Can someone tell -me a disk that supports more than ATA log pages 1 and 6? I need to -get a disk so I can test this functionality, when I add it. - -Perhaps modify the -q option (quiet mode) so that it only warns of ATA -errors if they have (say) taken place in the last 168 hours (week). - -Parse and print more attribute flag meanings (IBM ones, eg performance -etc). - -smartd: -------- - -Perhaps change <nomailer> special argument to -m to have also -<nomailer_fork> which would actually work with -M exec to run the -executable/script in the background rather than in the foreground. -But let's wait for someone to request this. At that point we should -probably use fork/exec rather than system(). - -Perhaps change smartd to look in /proc/ide and /proc/scsi to see what -exists? If something doesn't exit then don't try to open it? This -should probably be the default option if there is no configuration -file. - -Add ability to monitor "worst" value from attributes (sometimes it -gets larger!) and to monitor the threshold value (sometimes it -changes!). - -General Fixes -------------- - -Fix lots of syntax like if (a != 0). This is now pretty much confined -to the SCSI-only parts of the code. - -Use consistent error codes in exit() calls diff --git a/sm5/VERSION b/sm5/VERSION deleted file mode 100644 index b4de39476..000000000 --- a/sm5/VERSION +++ /dev/null @@ -1 +0,0 @@ -11 diff --git a/sm5/WARNINGS b/sm5/WARNINGS deleted file mode 100644 index f46bde5ea..000000000 --- a/sm5/WARNINGS +++ /dev/null @@ -1,16 +0,0 @@ -The following are controllers/drives where there have been reports of -serious problems (eg system lockup): - -SYSTEM: Dell servers using AACRAID (SCSI) -PROBLEM: Locked up, needed to be rebooted -REPORTER: drew@eastvan.bc.ca -LINK: http://sourceforge.net/mailarchive/forum.php?thread_id=1311313&forum_id=12495 - -SYSTEM: Box with Promise 20265 IDE-controller (pdc202xx-driver) and > 2.4.18 kernel with ide-taskfile support -PROBLEM: Smartctl locks system solid when used on /dev/hd[ef]. -REPORTER: Georg Acher <acher@in.tum.de> -LINK: http://sourceforge.net/mailarchive/forum.php?thread_id=1457979&forum_id=12495 -NOTE: Lockup doesn't happen with 2.4.18 kernel, and doesn't affect /dev/hd[a-d] - This appears to be a problem with the pdc202xx-driver and has been reported - to the pcdx maintainers. If you enable the the Promise-BIOS (ATA100-BIOS) then - everything will work fine. But if you disable it, then the machine will hang. diff --git a/sm5/add b/sm5/add deleted file mode 100755 index 7f635870d..000000000 --- a/sm5/add +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -# -# This is a utility called in the Makefile. It's used together with -# the file "counter" to automatically increment release numbers. -# -a=`cat VERSION` -let a+=1 -echo $a diff --git a/sm5/atacmds.c b/sm5/atacmds.c deleted file mode 100644 index d8e82d534..000000000 --- a/sm5/atacmds.c +++ /dev/null @@ -1,1530 +0,0 @@ -/* - * atacmds.c - * - * Home page of code is: http://smartmontools.sourceforge.net - * - * Copyright (C) 2002-3 Bruce Allen <smartmontools-support@lists.sourceforge.net> - * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org> - * Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org> - * - * 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 Software Foundation; either version 2, or (at your option) - * any later version. - * - * You should have received a copy of the GNU General Public License - * (for example COPYING); if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * This code was originally developed as a Senior Thesis by Michael Cornwell - * at the Concurrent Systems Laboratory (now part of the Storage Systems - * Research Center), Jack Baskin School of Engineering, University of - * California, Santa Cruz. http://ssrc.soe.ucsc.edu/ - * - */ - -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <stdlib.h> -#include <ctype.h> -#include "atacmds.h" -#include "utility.h" -#include "extern.h" - -const char *atacmds_c_cvsid="$Id: atacmds.c,v 1.98 2003/04/28 18:37:02 ballen4705 Exp $" ATACMDS_H_CVSID EXTERN_H_CVSID UTILITY_H_CVSID; - -// for passing global control variables -extern smartmonctrl *con; - -// These Drive Identity tables are taken from hdparm 5.2, and are also -// given in the ATA/ATAPI specs for the IDENTIFY DEVICE command. Note -// that SMART was first added into the ATA/ATAPI-3 Standard with -// Revision 3 of the document, July 25, 1995. Look at the "Document -// Status" revision commands at the beginning of -// http://www.t13.org/project/d2008r6.pdf to see this. -#define NOVAL_0 0x0000 -#define NOVAL_1 0xffff -/* word 81: minor version number */ -#define MINOR_MAX 0x1e -const char *minor_str[] = { /* word 81 value: */ - "Device does not report version", /* 0x0000 */ - "ATA-1 X3T9.2 781D prior to revision 4", /* 0x0001 */ - "ATA-1 published, ANSI X3.221-1994", /* 0x0002 */ - "ATA-1 X3T9.2 781D revision 4", /* 0x0003 */ - "ATA-2 published, ANSI X3.279-1996", /* 0x0004 */ - "ATA-2 X3T10 948D prior to revision 2k", /* 0x0005 */ - "ATA-3 X3T10 2008D revision 1", /* 0x0006 */ /* SMART NOT INCLUDED */ - "ATA-2 X3T10 948D revision 2k", /* 0x0007 */ - "ATA-3 X3T10 2008D revision 0", /* 0x0008 */ - "ATA-2 X3T10 948D revision 3", /* 0x0009 */ - "ATA-3 published, ANSI X3.298-199x", /* 0x000a */ - "ATA-3 X3T10 2008D revision 6", /* 0x000b */ /* 1st VERSION WITH SMART */ - "ATA-3 X3T13 2008D revision 7 and 7a", /* 0x000c */ - "ATA/ATAPI-4 X3T13 1153D revision 6", /* 0x000d */ - "ATA/ATAPI-4 T13 1153D revision 13", /* 0x000e */ - "ATA/ATAPI-4 X3T13 1153D revision 7", /* 0x000f */ - "ATA/ATAPI-4 T13 1153D revision 18", /* 0x0010 */ - "ATA/ATAPI-4 T13 1153D revision 15", /* 0x0011 */ - "ATA/ATAPI-4 published, ANSI NCITS 317-1998", /* 0x0012 */ - "ATA/ATAPI-5 T13 1321D revision 3", /* 0x0013 */ - "ATA/ATAPI-4 T13 1153D revision 14", /* 0x0014 */ - "ATA/ATAPI-5 T13 1321D revision 1", /* 0x0015 */ - "ATA/ATAPI-5 published, ANSI NCITS 340-2000", /* 0x0016 */ - "ATA/ATAPI-4 T13 1153D revision 17", /* 0x0017 */ - "ATA/ATAPI-6 T13 1410D revision 0", /* 0x0018 */ - "ATA/ATAPI-6 T13 1410D revision 3a", /* 0x0019 */ - "ATA/ATAPI-7 T13 1532D revision 1", /* 0x001a */ - "ATA/ATAPI-6 T13 1410D revision 2", /* 0x001b */ - "ATA/ATAPI-6 T13 1410D revision 1", /* 0x001c */ - "reserved", /* 0x001d */ - "ATA/ATAPI-7 T13 1532D revision 0" /* 0x001e */ -}; - -// NOTE ATA/ATAPI-4 REV 4 was the LAST revision where the device -// attribute structures were NOT completely vendor specific. So any -// disk that is ATA/ATAPI-4 or above can not be trusted to show the -// vendor values in sensible format. - -// Negative values below are because it doesn't support SMART -const int actual_ver[] = { - /* word 81 value: */ - 0, /* 0x0000 WARNING: */ - 1, /* 0x0001 WARNING: */ - 1, /* 0x0002 WARNING: */ - 1, /* 0x0003 WARNING: */ - 2, /* 0x0004 WARNING: This array */ - 2, /* 0x0005 WARNING: corresponds */ - -3, /*<== */ /* 0x0006 WARNING: *exactly* */ - 2, /* 0x0007 WARNING: to the ATA/ */ - -3, /*<== */ /* 0x0008 WARNING: ATAPI version */ - 2, /* 0x0009 WARNING: listed in */ - 3, /* 0x000a WARNING: the */ - 3, /* 0x000b WARNING: minor_str */ - 3, /* 0x000c WARNING: array */ - 4, /* 0x000d WARNING: above. */ - 4, /* 0x000e WARNING: */ - 4, /* 0x000f WARNING: If you change */ - 4, /* 0x0010 WARNING: that one, */ - 4, /* 0x0011 WARNING: change this one */ - 4, /* 0x0012 WARNING: too!!! */ - 5, /* 0x0013 WARNING: */ - 4, /* 0x0014 WARNING: */ - 5, /* 0x0015 WARNING: */ - 5, /* 0x0016 WARNING: */ - 4, /* 0x0017 WARNING: */ - 6, /* 0x0018 WARNING: */ - 6, /* 0x0019 WARNING: */ - 7, /* 0x001a WARNING: */ - 6, /* 0x001b WARNING: */ - 6, /* 0x001c WARNING: */ - 0, /* 0x001d WARNING: */ - 7 /* 0x001e WARNING: */ -}; - -// When you add additional items to this list, you should then: -// 0 -- update this list -// 1 -- modify the following function parse_attribute_def() -// 2 -- modify ataPrintSmartAttribRawValue() -// 3 - modify ataPrintSmartAttribName() -// 4 -- add #define PRESET_N_DESCRIPTION at top of knowndrives.c -// 5 -- add drive in question into knowndrives[] table in knowndrives.c -// 6 -- update smartctl.8 -// 7 -- update smartd.8 -// 8 -- do "make smartd.conf.5" to update smartd.conf.5 -// 9 -- update CHANGELOG file -const char *vendorattributeargs[] = { - // 0 defs[9]=1 - "9,minutes", - // 1 defs[9]=3 - "9,seconds", - // 2 defs[9]=2 - "9,temp", - // 3 defs[220]=1 - "220,temp", - // 4 defs[*]=253 - "N,raw8", - // 5 defs[*]=254 - "N,raw16", - // 6 defs[*]=255 - "N,raw48", - // 7 defs[200]=1 - "200,writeerrorcount", - // 8 defs[9]=4 - "9,halfminutes", - // 9 defs[194]=1 - "194,10xCelsius", - // 10 defs[194]=2 - "194,unknown", - // NULL should always terminate the array - NULL -}; - -// 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(char *pair, unsigned char *defs){ - int i,j; - char temp[32]; - - // look along list and see if we find the pair - for (i=0; vendorattributeargs[i] && strcmp(pair, vendorattributeargs[i]); i++); - - switch (i) { - case 0: - // attribute 9 is power on time in minutes - defs[9]=1; - return 0; - case 1: - // attribute 9 is power-on-time in seconds - defs[9]=3; - return 0; - case 2: - // attribute 9 is temperature in celsius - defs[9]=2; - return 0; - case 3: - // attribute 220 is temperature in celsius - defs[220]=1; - return 0; - case 4: - // print all attributes in raw 8-bit form - for (j=0; j<256; j++) - defs[j]=253; - return 0; - case 5: - // print all attributes in raw 16-bit form - for (j=0; j<256; j++) - defs[j]=254; - return 0; - case 6: - // print all attributes in raw 48-bit form - for (j=0; j<256; j++) - defs[j]=255; - return 0; - case 7: - // attribute 200 is write error count - defs[200]=1; - return 0; - case 8: - // attribute 9 increments once every 30 seconds (power on time - // measure) - defs[9]=4; - return 0; - case 9: - // attribute 194 is ten times disk temp in Celsius - defs[194]=1; - return 0; - case 10: - // attribute 194 is unknown - defs[194]=2; - return 0; - default: - // pair not found - break; - } - // At this point, either the pair was not found, or it is of the - // form N,uninterpreted, in which case we need to parse N - j=sscanf(pair,"%d,%14s", &i, temp); - - // if no match to pattern, unrecognized - if (j!=2 || i<0 || i >255) - return 1; - - // check for recognized strings - if (!strcmp(temp, "raw8")) { - defs[i]=253; - return 0; - } - - // check for recognized strings - if (!strcmp(temp, "raw16")) { - defs[i]=254; - return 0; - } - - // check for recognized strings - if (!strcmp(temp, "raw48")) { - defs[i]=255; - return 0; - } - - // didn't recognize the string - return 1; -} - -// Structure used in sorting the array vendorattributeargs[]. -typedef struct vaa_pair_s { - const char *vaa; - const char *padded_vaa; -} vaa_pair; - -// Returns a copy of s with all numbers of less than three digits padded with -// leading zeros. Returns NULL if there isn't enough memory available. The -// memory for the string is dynamically allocated and should be freed by the -// caller. -char *pad_numbers(const char *s) -{ - char c, *t, *u; - const char *r; - int i, len, ndigits = 0; - - // Allocate the maximum possible amount of memory needed. - if (!(t = (char *)malloc(strlen(s)*2+2))) - return NULL; - - // Copy the string s to t, padding any numbers of less than three digits - // with leading zeros. The string is copied backwards to simplify the code. - r = s + strlen(s); - u = t; - while (( r-- >= s)) { - if (isdigit(*r)) - ndigits++; - else if (ndigits > 0) { - while (ndigits++ < 3) - *u++ = '0'; - ndigits = 0; - } - *u++ = *r; - } - *u = '\0'; - - // Reverse the string in t. - len = strlen(t); - for (i = 0; i < len/2; i++) { - c = t[i]; - t[i] = t[len-1-i]; - t[len-1-i] = c; - } - - return t; -} - -// Comparison function for qsort(). Used by sort_vendorattributeargs(). -int compare_vaa_pairs(const void *a, const void *b) -{ - vaa_pair *p = (vaa_pair *)a; - vaa_pair *q = (vaa_pair *)b; - - return strcmp(p->padded_vaa, q->padded_vaa); -} - -// Returns a sorted list of vendorattributeargs or NULL if there is not enough -// memory available. The memory for the list is allocated dynamically and -// should be freed by the caller. -// To perform the sort, any numbers in the strings are padded out to three -// digits by adding leading zeros. For example, -// -// "9,minutes" becomes "009,minutes" -// "N,raw16" becomes "N,raw016" -// -// and the original strings are paired with the padded strings. The list of -// pairs is then sorted by comparing the padded strings (using strcmp) and the -// result is then the list of unpadded strings. -// -const char **sort_vendorattributeargs(void) { - const char **ps, **sorted_list = NULL; - vaa_pair *pairs, *pp; - int count, i; - - // Figure out how many strings are in vendorattributeargs[] (not including - // the terminating NULL). - count = (sizeof vendorattributeargs) / sizeof(char *) - 1; - - // Construct a list of pairs of strings from vendorattributeargs[] and their - // padded equivalents. - if (!(pairs = (vaa_pair *)malloc(sizeof(vaa_pair) * count))) - goto END; - for (ps = vendorattributeargs, pp = pairs; *ps; ps++, pp++) { - pp->vaa = *ps; - if (!(pp->padded_vaa = pad_numbers(*ps))) - goto END; - } - - // Sort the array of vaa_pair structures by comparing the padded strings - // using strcmp(). - qsort(pairs, count, sizeof(vaa_pair), compare_vaa_pairs); - - // Construct the sorted list of strings. - if (!(sorted_list = (const char **)malloc(sizeof vendorattributeargs))) - goto END; - for (ps = sorted_list, pp = pairs, i = 0; i < count; ps++, pp++, i++) - *ps = pp->vaa; - *ps = NULL; - -END: - if (pairs) { - for (i = 0; i < count; i++) - if (pairs[i].padded_vaa) - free((void *)pairs[i].padded_vaa); - free((void *)pairs); - } - - // If there was a problem creating the list then sorted_list should now - // contain NULL. - return sorted_list; -} - -// Function to return a multiline string containing a list of the arguments in -// vendorattributeargs[]. The strings are preceeded by tabs and followed -// (except for the last) by newlines. -// This function allocates the required memory for the string and the caller -// must use free() to free it. It returns NULL if the required memory can't -// be allocated. -char *create_vendor_attribute_arg_list(void){ - const char **ps, **sorted; - char *s; - int len; - - // Get a sorted list of vendor attribute arguments. If the sort fails - // (which should only happen if the system is really low on memory) then just - // use the unordered list. - if (!(sorted = (const char **) sort_vendorattributeargs())) - sorted = vendorattributeargs; - - // Calculate the required number of characters - len = 1; // At least one char ('\0') - for (ps = sorted; *ps != NULL; ps++) { - len += 1; // For the tab - len += strlen(*ps); // For the actual argument string - if (*(ps+1)) - len++; // For the newline if required - } - - // Attempt to allocate memory for the string - if (!(s = (char *)malloc(len))) - return NULL; - - // Construct the string - *s = '\0'; - for (ps = sorted; *ps != NULL; ps++) { - strcat(s, "\t"); - strcat(s, *ps); - if (*(ps+1)) - strcat(s, "\n"); - } - - free(sorted); - - // Return a pointer to the string - return s; -} - - -// PURPOSE -// This is an interface routine meant to isolate the OS dependent -// parts of the code, and to provide a debugging interface. Each -// different port and OS needs to provide it's own interface. This -// is the linux one. -// DETAILED DESCRIPTION OF ARGUMENTS -// device: is the file descriptor provided by open() -// command: defines the different operations. -// select: additional input data if needed (which log, which type of -// self-test). -// data: location to write output data, if needed (512 bytes). -// Note: not all commands use all arguments. -// RETURN VALUES -// -1 if the command failed -// 0 if the command succeeded, -// STATUS_CHECK routine: -// -1 if the command failed -// 0 if the command succeeded and disk SMART status is "OK" -// 1 if the command succeeded and disk SMART status is "FAILING" - - -// huge value of buffer size needed because HDIO_DRIVE_CMD assumes -// that buff[3] is the data size. Since the SMART_AUTOSAVE and -// SMART_AUTO_OFFLINE use values of 0xf1 and 0xf8 we need the space. -// Otherwise a 4+512 byte buffer would be enough. -#define STRANGE_BUFFER_LENGTH (4+512*0xf8) - -int os_specific_handler(int device, smart_command_set command, int select, char *data){ - unsigned char buff[STRANGE_BUFFER_LENGTH]; - int retval, copydata=0; - - // See struct hd_drive_cmd_hdr in hdreg.h - // buff[0]: ATA COMMAND CODE REGISTER - // buff[1]: ATA SECTOR NUMBER REGISTER - // buff[2]: ATA FEATURES REGISTER - // buff[3]: ATA SECTOR COUNT REGISTER - - // clear out buff. Large enough for HDIO_DRIVE_CMD (4+512 bytes) - memset(buff, 0, STRANGE_BUFFER_LENGTH); - - buff[0]=WIN_SMART; - switch (command){ - case READ_VALUES: - buff[2]=SMART_READ_VALUES; - copydata=buff[3]=1; - break; - case READ_THRESHOLDS: - buff[2]=SMART_READ_THRESHOLDS; - copydata=buff[1]=buff[3]=1; - break; - case READ_LOG: - buff[2]=SMART_READ_LOG_SECTOR; - buff[1]=select; - copydata=buff[3]=1; - break; - case IDENTIFY: - buff[0]=WIN_IDENTIFY; - copydata=buff[3]=1; - break; - case PIDENTIFY: - buff[0]=WIN_PIDENTIFY; - copydata=buff[3]=1; - break; - case ENABLE: - buff[2]=SMART_ENABLE; - buff[1]=1; - break; - case DISABLE: - buff[2]=SMART_DISABLE; - buff[1]=1; - break; - case STATUS: - // this command only says if SMART is working. It could be - // replaced with STATUS_CHECK below. - buff[2]=SMART_STATUS; - break; - case AUTO_OFFLINE: - buff[2]=SMART_AUTO_OFFLINE; - buff[3]=select; // YET NOTE - THIS IS A NON-DATA COMMAND!! - break; - case AUTOSAVE: - buff[2]=SMART_AUTOSAVE; - buff[3]=select; // YET NOTE - THIS IS A NON-DATA COMMAND!! - break; - case IMMEDIATE_OFFLINE: - buff[2]=SMART_IMMEDIATE_OFFLINE; - buff[1]=select; - break; - // the command uses HDIO_DRIVE_TASK and has different syntax than - // the other commands. - case STATUS_CHECK: - buff[1]=SMART_STATUS; - break; - default: - pout("Unrecognized command %d in os_specific_handler()\n", command); - exit(1); - break; - } - - // There are two different types of ioctls(). The HDIO_DRIVE_TASK - // one is this: - if (command==STATUS_CHECK){ - unsigned const char normal_lo=0x4f, normal_hi=0xc2; - unsigned const char failed_lo=0xf4, failed_hi=0x2c; - buff[4]=normal_lo; - buff[5]=normal_hi; - - // HDIO_DRIVE_TASK IOCTL -#ifdef HDIO_DRIVE_TASK - if ((retval=ioctl(device, HDIO_DRIVE_TASK, buff))) -#endif - return -1; - - // Cyl low and Cyl high unchanged means "Good SMART status" - if (buff[4]==normal_lo && buff[5]==normal_hi) - return 0; - - // These values mean "Bad SMART status" - if (buff[4]==failed_lo && buff[5]==failed_hi) - return 1; - - // We haven't gotten output that makes sense; print out some debugging info - syserror("Error SMART Status command failed"); - pout("Please get assistance from %s\n",PROJECTHOME); - pout("Register values returned from SMART Status command are:\n"); - pout("CMD=0x%02x\n",(int)buff[0]); - pout("FR =0x%02x\n",(int)buff[1]); - pout("NS =0x%02x\n",(int)buff[2]); - pout("SC =0x%02x\n",(int)buff[3]); - pout("CL =0x%02x\n",(int)buff[4]); - pout("CH =0x%02x\n",(int)buff[5]); - pout("SEL=0x%02x\n",(int)buff[6]); - return -1; - } - - // We are now doing the HDIO_DRIVE_CMD type ioctl. - if ((retval=ioctl(device, HDIO_DRIVE_CMD, buff))) - return -1; - - if (copydata) - memcpy(data, buff+4, 512); - - return 0; -} - -static char *commandstrings[]={ - [ENABLE]= "SMART ENABLE", - [DISABLE]= "SMART DISABLE", - [AUTOSAVE]= "SMART AUTOMATIC ATTRIBUTE SAVE", - [IMMEDIATE_OFFLINE]="SMART IMMEDIATE OFFLINE", - [AUTO_OFFLINE]= "SMART AUTO OFFLINE", - [STATUS]= "SMART STATUS", - [STATUS_CHECK]= "SMART STATUS CHECK", - [READ_VALUES]= "SMART READ ATTRIBUTE VALUES", - [READ_THRESHOLDS]= "SMART READ ATTRIBUTE THRESHOLDS", - [READ_LOG]= "SMART READ LOG", - [IDENTIFY]= "IDENTIFY DEVICE" , - [PIDENTIFY]= "IDENTIFY PACKET DEVICE" -}; - -void prettyprint(unsigned char *stuff, char *name){ - int i,j; - pout("\n===== [%s] DATA START (BASE-16) =====\n", name); - for (i=0; i<32; i++){ - pout("%03d-%03d: ", 16*i, 16*(i+1)-1); - for (j=0; j<15; j++) - pout("%02x ",*stuff++); - pout("%02x\n",*stuff++); - } - pout("===== [%s] DATA END (512 Bytes) =====\n\n", name); -} - -// This function provides the pretty-print reporting -int smartcommandhandler(int device, smart_command_set command, int select, char *data){ - int retval; - - // This conditional is true for commands that return data - int getsdata=(command==PIDENTIFY || - command==IDENTIFY || - command==READ_LOG || - command==READ_THRESHOLDS || - command==READ_VALUES); - - // If reporting is enabled, say what the command will be before it's executed - if (con->reportataioctl){ - // conditional is true for commands that use parameters - int usesparam=(command==READ_LOG || - command==AUTO_OFFLINE || - command==AUTOSAVE || - command==IMMEDIATE_OFFLINE); - - pout("\nREPORT-IOCTL: DeviceFD=%d Command=%s", device, commandstrings[command]); - if (usesparam) - pout(" InputParameter=%d\n", select); - else - pout("\n"); - } - - if (getsdata && data==NULL){ - pout("REPORT-IOCTL: Unable to execute command %s : data destination address is NULL\n", commandstrings[command]); - return -1; - } - - // now execute the command - retval=os_specific_handler(device, command, select, data); - - // If reporting is enabled, say what output was produced by the command - if (con->reportataioctl){ - pout("REPORT-IOCTL: DeviceFD=%d Command=%s returned %d\n", device, commandstrings[command], retval); - // if requested, pretty-print the output data structure - if (con->reportataioctl>1 && getsdata) - prettyprint((unsigned char *)data, commandstrings[command]); - } - return retval; -} - - -// This function computes the checksum of a single disk sector (512 -// bytes). Returns zero if checksum is OK, nonzero if the checksum is -// incorrect. The size (512) is correct for all SMART structures. -unsigned char checksum(unsigned char *buffer){ - unsigned char sum=0; - int i; - - for (i=0; i<512; i++) - sum+=buffer[i]; - - return sum; -} - -// Reads current Device Identity info (512 bytes) into buf -int ataReadHDIdentity (int device, struct hd_driveid *buf){ - unsigned short driveidchecksum; - - if (smartcommandhandler(device, IDENTIFY, 0, (char *)buf)){ - // See if device responds to packet command... - if (smartcommandhandler(device, PIDENTIFY, 0, (char *)buf)){ - syserror("Error ATA GET HD Identity Failed"); - return -1; - } - } - -#if 0 - // The following ifdef is a HACK to distinguish different versions - // of the header file defining hd_driveid -#ifdef CFA_REQ_EXT_ERROR_CODE - driveidchecksum=buf->integrity_word; -#else - // Note -- the declaration that appears in - // /usr/include/linux/hdreg.h: short words160_255[95], is WRONG. - // It should say: short words160_255[96]. I have written to Andre - // Hedrick about this on Oct 17 2002. Please remove this comment - // once the fix has made it into the stock kernel tree. - driveidchecksum=buf->words160_255[95]; -#endif -#else - // This way is ugly and you may feel ill -- but it always works... - { - unsigned short *rawstructure= - (unsigned short *)buf; - driveidchecksum=rawstructure[255]; - } -#endif - - if ((driveidchecksum & 0x00ff) == 0x00a5 && checksum((unsigned char *)buf)) - checksumwarning("Drive Identity Structure"); - - return 0; -} - -// Returns ATA version as an integer, and a pointer to a string -// describing which revision. Note that Revision 0 of ATA-3 does NOT -// support SMART. For this one case we return -3 rather than +3 as -// the version number. See notes above. -int ataVersionInfo (const char** description, struct hd_driveid *drive, unsigned short *minor){ - unsigned short major; - int i; - - // check that arrays at the top of this file are defined - // consistently - if (sizeof(minor_str) != sizeof(char *)*(1+MINOR_MAX)){ - pout("Internal error in ataVersionInfo(). minor_str[] size %d\n" - "is not consistent with value of MINOR_MAX+1 = %d\n", - sizeof(minor_str)/sizeof(char *), MINOR_MAX+1); - fflush(NULL); - abort(); - } - if (sizeof(actual_ver) != sizeof(int)*(1+MINOR_MAX)){ - pout("Internal error in ataVersionInfo(). actual_ver[] size %d\n" - "is not consistent with value of MINOR_MAX = %d\n", - sizeof(actual_ver)/sizeof(int), MINOR_MAX+1); - fflush(NULL); - abort(); - } - - // get major and minor ATA revision numbers -#ifdef __NEW_HD_DRIVE_ID - major=drive->major_rev_num; - *minor=drive->minor_rev_num; -#else - major=drive->word80; - *minor=drive->word81; -#endif - - // First check if device has ANY ATA version information in it - if (major==NOVAL_0 || major==NOVAL_1) { - *description=NULL; - return -1; - } - - // The minor revision number has more information - try there first - if (*minor && (*minor<=MINOR_MAX)){ - int std = actual_ver[*minor]; - if (std) { - *description=minor_str[*minor]; - return std; - } - } - - // HDPARM has a very complicated algorithm from here on. Since SMART only - // exists on ATA-3 and later standards, let's punt on this. If you don't - // like it, please fix it. The code's in CVS. - for (i=15; i>0; i--) - if (major & (0x1<<i)) - break; - - *description=NULL; - if (i==0) - return 1; - else - return i;; -} - -// returns 1 if SMART supported, 0 if not supported or can't tell -int ataSmartSupport(struct hd_driveid *drive){ - unsigned short word82,word83; - - // get correct bits of IDENTIFY DEVICE structure -#ifdef __NEW_HD_DRIVE_ID - word82=drive->command_set_1; - word83=drive->command_set_2; -#else - word82=drive->command_sets; - word83=drive->word83; -#endif - - // Note this does not work for ATA3 < Revision 6, when word82 and word83 were added - // we should check for ATA3 Rev 0 in minor identity code... - return (word83 & 0x0001<<14) && !(word83 & 0x0001<<15) && (word82 & 0x0001); -} - -// returns 1 if SMART enabled, 0 if SMART disabled, -1 if can't tell -int ataIsSmartEnabled(struct hd_driveid *drive){ - unsigned short word85,word87; - - // Get correct bits of IDENTIFY DRIVE structure -#ifdef __NEW_HD_DRIVE_ID - word85=drive->cfs_enable_1; - word87=drive->csf_default; -#else - word85=drive->word85; - word87=drive->word87; -#endif - - if ((word87 & 0x0001<<14) && !(word87 & 0x0001<<15)) - // word85 contains valid information, so - return word85 & 0x0001; - - // Since we can't rely word85, we don't know if SMART is enabled. - return -1; -} - - -// Reads SMART attributes into *data -int ataReadSmartValues(int device, struct ata_smart_values *data){ - - if (smartcommandhandler(device, READ_VALUES, 0, (char *)data)){ - syserror("Error SMART Values Read failed"); - return -1; - } - - // compute checksum - if (checksum((unsigned char *)data)) - checksumwarning("SMART Attribute Data Structure"); - - return 0; -} - -// swap two bytes. Point to low address -void swap2(char *location){ - char tmp=*location; - *location=*(location+1); - *(location+1)=tmp; - return; -} - -// swap four bytes. Point to low address -void swap4(char *location){ - char tmp=*location; - *location=*(location+3); - *(location+3)=tmp; - swap2(location+1); - return; -} - -// This corrects some quantities that are byte reversed in the SMART -// SELF TEST LOG -void fixsamsungselftestlog(struct ata_smart_selftestlog *data){ - int i; - - // swap with one byte of reserved - swap2((char *)&(data->mostrecenttest)); - - // LBA low register (here called 'selftestnumber") is byte swapped - // with Self-test execution status byte. - for (i=0; i<21; i++) - swap2((char *)&(data->selftest_struct[i].selftestnumber)); - - return; -} - -// Reads the Self Test Log (log #6) -int ataReadSelfTestLog (int device, struct ata_smart_selftestlog *data){ - - // get data from device - if (smartcommandhandler(device, READ_LOG, 0x06, (char *)data)){ - syserror("Error SMART Error Self-Test Log Read failed"); - return -1; - } - - // compute its checksum, and issue a warning if needed - if (checksum((unsigned char *)data)) - checksumwarning("SMART Self-Test Log Structure"); - - // fix firmware bugs in self-test log - if (con->fixfirmwarebug == FIX_SAMSUNG) - fixsamsungselftestlog(data); - - return 0; -} - - -// Reads the Log Directory (log #0). Note: NO CHECKSUM!! -int ataReadLogDirectory (int device, struct ata_smart_log_directory *data){ - - // get data from device - if (smartcommandhandler(device, READ_LOG, 0x00, (char *)data)){ - return -1; - } - return 0; -} - -// This corrects some quantities that are byte reversed in the SMART -// ATA ERROR LOG -void fixsamsungerrorlog(struct ata_smart_errorlog *data){ - int i,j; - - // Device error count in bytes 452-3 - swap2((char *)&(data->ata_error_count)); - - // step through 5 error log data structures - for (i=0; i<5; i++){ - // step through 5 command data structures - for (j=0; j<5; j++) - // Command data structure 4-byte millisec timestamp - swap4((char *)&(data->errorlog_struct[i].commands[j].timestamp)); - // Error data structure life timestamp - swap2((char *)&(data->errorlog_struct[i].error_struct.timestamp)); - } -} - -// Reads the Error Log (log #1) -int ataReadErrorLog (int device, struct ata_smart_errorlog *data){ - - // get data from device - if (smartcommandhandler(device, READ_LOG, 0x01, (char *)data)){ - syserror("Error SMART Error Log Read failed"); - return -1; - } - - // compute its checksum, and issue a warning if needed - if (checksum((unsigned char *)data)) - checksumwarning("SMART ATA Error Log Structure"); - - // Some disks have the byte order reversed in some SMART Summary - // Error log entries - if (con->fixfirmwarebug == FIX_SAMSUNG) - fixsamsungerrorlog(data); - - return 0; -} - -int ataReadSmartThresholds (int device, struct ata_smart_thresholds *data){ - - // get data from device - if (smartcommandhandler(device, READ_THRESHOLDS, 0, (char *)data)){ - syserror("Error SMART Thresholds Read failed"); - return -1; - } - - // compute its checksum, and issue a warning if needed - if (checksum((unsigned char *)data)) - checksumwarning("SMART Attribute Thresholds Structure"); - - return 0; -} - -int ataEnableSmart (int device ){ - if (smartcommandhandler(device, ENABLE, 0, NULL)){ - syserror("Error SMART Enable failed"); - return -1; - } - return 0; -} - -int ataDisableSmart (int device ){ - - if (smartcommandhandler(device, DISABLE, 0, NULL)){ - syserror("Error SMART Disable failed"); - return -1; - } - return 0; -} - -int ataEnableAutoSave(int device){ - if (smartcommandhandler(device, AUTOSAVE, 241, NULL)){ - syserror("Error SMART Enable Auto-save failed"); - return -1; - } - return 0; -} - -int ataDisableAutoSave(int device){ - - if (smartcommandhandler(device, AUTOSAVE, 0, NULL)){ - syserror("Error SMART Disable Auto-save failed"); - return -1; - } - return 0; -} - -// Note that in the ATA-5 standard the Enable/Disable AutoOffline -// command is marked "OBSOLETE". Curiously, I could not find it -// documented in ANY of the ATA specifications. In other words, it's -// been obsolete forever. However some vendors (eg, IBM) seem to be -// using this command anyway. For example see the IBM Travelstar -// 40GNX hard disk drive specifications page 164 Revision 1.1 22 Apr -// 2002. This gives a detailed description of the command, although -// the drive claims to comply with the ATA/ATAPI-5 Revision 3 -// standard! The latter document makes no mention of this command at -// all, other than to say that it is "obsolete". -int ataEnableAutoOffline (int device ){ - - /* timer hard coded to 4 hours */ - if (smartcommandhandler(device, AUTO_OFFLINE, 248, NULL)){ - syserror("Error SMART Enable Automatic Offline failed"); - return -1; - } - return 0; -} - -// Another Obsolete Command. See comments directly above, associated -// with the corresponding Enable command. -int ataDisableAutoOffline (int device ){ - - if (smartcommandhandler(device, AUTO_OFFLINE, 0, NULL)){ - syserror("Error SMART Disable Automatic Offline failed"); - return -1; - } - return 0; -} - - -// This function does NOTHING except tell us if SMART is working & -// enabled on the device. See ataSmartStatus2() for one that actually -// returns SMART status. -int ataSmartStatus (int device ){ - - if (smartcommandhandler(device, STATUS, 0, NULL)){ - syserror("Error Return SMART Status via HDIO_DRIVE_CMD failed"); - return -1; - } - return 0; -} - -// If SMART is enabled, supported, and working, then this call is -// guaranteed to return 1, else zero. Silent inverse of -// ataSmartStatus() -int ataDoesSmartWork(int device){ - return !smartcommandhandler(device, STATUS, 0, NULL); -} - -#ifdef HDIO_DRIVE_TASK -// This function uses a different interface (DRIVE_TASK) than the -// other commands in this file. -int ataSmartStatus2(int device){ - - int returnval=smartcommandhandler(device, STATUS_CHECK, 0, NULL); - - if (returnval==-1){ - syserror("Error SMART Status command via HDIO_DRIVE_TASK failed"); - pout("Rebuild older linux 2.2 kernels with HDIO_DRIVE_TASK support enabled\n"); - } - - return returnval; -} -#else -// Just a hack so that the code compiles on -// 2.2 kernels without HDIO_DRIVE TASK support. -// Should be fixed by putting in a call to code -// that compares smart data to thresholds. -int ataSmartStatus2(int device){ - pout("This code was compiled on a machine whose kernel header\n" - "files do not support the HDIO_DRIVE_TASK ioctl().\n" - "Compile on a linux 2.2 kernel box with HDIO_DRIVE_TASK\n" - "support enabled, or on a 2.4 kernel box, please.\n"); - return ataSmartStatus(device); -} -#endif - - -// This is the way to execute ALL tests: offline, short self-test, -// extended self test, with and without captive mode, etc. -int ataSmartTest(int device, int testtype){ - char cmdmsg[128],*type,*captive; - int errornum; - int cap; - - // Boolean, if set, says test is captive - cap=testtype & CAPTIVE_MASK; - - // Set up strings that describe the type of test - if (cap) - captive="captive"; - else - captive="off-line"; - - if (testtype==OFFLINE_FULL_SCAN) - type="off-line"; - else if (testtype==SHORT_SELF_TEST || testtype==SHORT_CAPTIVE_SELF_TEST) - type="Short self-test"; - else if (testtype==EXTEND_SELF_TEST || testtype==EXTEND_CAPTIVE_SELF_TEST) - type="Extended self-test"; - else if (testtype==CONVEYANCE_SELF_TEST || testtype==CONVEYANCE_CAPTIVE_SELF_TEST) - type="Conveyance self-test"; - else if (testtype==SELECTIVE_SELF_TEST || testtype==SELECTIVE_CAPTIVE_SELF_TEST) - type="Selective self-test"; - else - type="[Unrecognized] self-test"; - - // Print ouf message that we are sending the command to test - if (testtype==ABORT_SELF_TEST) - sprintf(cmdmsg,"Abort SMART off-line mode self-test routine"); - else - sprintf(cmdmsg,"Execute SMART %s routine immediately in %s mode",type,captive); - pout("Sending command: \"%s\".\n",cmdmsg); - - // Now send the command to test - errornum=smartcommandhandler(device, IMMEDIATE_OFFLINE, testtype, NULL); - - if (errornum && !(cap && errno==EIO)){ - char errormsg[128]; - sprintf(errormsg,"Command \"%s\" failed",cmdmsg); - syserror(errormsg); - pout("\n"); - return -1; - } - - // Since the command succeeded, tell user - if (testtype==ABORT_SELF_TEST) - pout("Self-testing aborted!\n"); - else - pout("Drive command \"%s\" successful.\nTesting has begun.\n",cmdmsg); - return 0; -} - -/* Test Time Functions */ -int TestTime(struct ata_smart_values *data,int testtype){ - switch (testtype){ - case OFFLINE_FULL_SCAN: - return (int) data->total_time_to_complete_off_line; - case SHORT_SELF_TEST: - case SHORT_CAPTIVE_SELF_TEST: - return (int) data->short_test_completion_time; - case EXTEND_SELF_TEST: - case EXTEND_CAPTIVE_SELF_TEST: - return (int) data->extend_test_completion_time; - default: - return 0; - } -} - -// This function tells you both about the ATA error log and the -// self-test error log capability. The bit is poorly documented in -// the ATA/ATAPI standard. -int isSmartErrorLogCapable ( struct ata_smart_values *data){ - return data->errorlog_capability & 0x01; -} -int isSupportExecuteOfflineImmediate(struct ata_smart_values *data){ - return data->offline_data_collection_capability & 0x01; -} - -int isGeneralPurposeLoggingCapable(struct hd_driveid *identity){ - unsigned short *rawwords=(unsigned short *)identity; - unsigned short word84, word87; - - word84=rawwords[84]; - word87=rawwords[87]; - - // If bit 14 of word 84 is set to one and bit 15 of word 84 is - // cleared to zero, the contents of word 84 contains valid support - // information. If not, support information is not valid in this - // word. - if ((word84>>14) == 0x01) - // If bit 5 of word 84 is set to one, the device supports the - // General Purpose Logging feature set. - return (word84 & (0x01 << 5)); - - // If bit 14 of word 87 is set to one and bit 15 of word 87 is - // cleared to zero, the contents of words (87:85) contain valid - // information. If not, information is not valid in these words. - if ((word87>>14) == 0x01) - // If bit 5 of word 87 is set to one, the device supports - // the General Purpose Logging feature set. - return (word87 & (0x01 << 5)); - - // not capable - return 0; -} - - -// Note in the ATA-5 standard, the following bit is listed as "Vendor -// Specific". So it may not be reliable. The only use of this that I -// have found is in IBM drives, where it is well-documented. See for -// example page 170, section 13.32.1.18 of the IBM Travelstar 40GNX -// hard disk drive specifications page 164 Revision 1.1 22 Apr 2002. -int isSupportAutomaticTimer(struct ata_smart_values *data){ - return data->offline_data_collection_capability & 0x02; -} -int isSupportOfflineAbort(struct ata_smart_values *data){ - return data->offline_data_collection_capability & 0x04; -} -int isSupportOfflineSurfaceScan(struct ata_smart_values *data){ - return data->offline_data_collection_capability & 0x08; -} -int isSupportSelfTest (struct ata_smart_values *data){ - return data->offline_data_collection_capability & 0x10; -} -int isSupportConveyanceSelfTest(struct ata_smart_values *data){ - return data->offline_data_collection_capability & 0x20; -} -int isSupportSelectiveSelfTest(struct ata_smart_values *data){ - return data->offline_data_collection_capability & 0x40; -} - - - -// 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(struct ata_smart_values *data, - struct ata_smart_thresholds *thresholds, - int onlyfailed){ - int i; - - // loop over all attributes - for (i=0; i<NUMBER_ATA_SMART_ATTRIBUTES; i++){ - - // pointers to disk's values and vendor's thresholds - struct ata_smart_attribute *disk=data->vendor_attributes+i; - struct 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 && disk->status.flag.prefailure) - return disk->id; - } - } - return 0; -} - - - -// 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(struct ata_smart_values *data, - struct ata_smart_thresholds *thresholds, - int n){ - struct ata_smart_attribute *disk; - struct ata_smart_threshold_entry *thre; - - if (n<0 || n>=NUMBER_ATA_SMART_ATTRIBUTES || !data || !thresholds) - return 0; - - // pointers to disk's values and vendor's thresholds - disk=data->vendor_attributes+n; - thre=thresholds->thres_entries+n; - - 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 (disk->status.flag.prefailure) - return disk->id; - else - return -1*(disk->id); -} - - -// 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. - -long long ataPrintSmartAttribRawValue(char *out, - struct ata_smart_attribute *attribute, - unsigned char *defs){ - long long rawvalue; - unsigned word[3]; - int j; - - // 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. - long long 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]; - } - - // Print six one-byte quantities. - if (defs[attribute->id]==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 (defs[attribute->id]==254){ - out+=sprintf(out, "%d %d %d", word[2], word[1], word[0]); - return rawvalue; - } - - // Print one six-byte quantity - if (defs[attribute->id]==255){ - out+=sprintf(out, "%llu", rawvalue); - return rawvalue; - } - - // 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]); - break; - // Power on time - case 9: - if (defs[9]==1){ - // minutes - long long tmp1=rawvalue/60; - long long tmp2=rawvalue%60; - out+=sprintf(out, "%lluh+%02llum", tmp1, tmp2); - } - else if (defs[9]==3){ - // seconds - long long hours=rawvalue/3600; - long long minutes=(rawvalue-3600*hours)/60; - long long seconds=rawvalue%60; - out+=sprintf(out, "%lluh+%02llum+%02llus", hours, minutes, seconds); - } - else if (defs[9]==4){ - // 30-second counter - long long tmp1=rawvalue/120; - long long tmp2=(rawvalue-120*tmp1)/2; - out+=sprintf(out, "%lluh+%02llum", tmp1, tmp2); - } - else - // hours - out+=sprintf(out, "%llu", rawvalue); //stored in hours - break; - // Temperature - case 194: - if (defs[194]==1){ - // ten times temperature in Celsius - int deg=word[0]/10; - int tenths=word[0]%10; - out+=sprintf(out, "%d.%d", deg, tenths); - } - else if (defs[194]==2) - // unknown attribute - out+=sprintf(out, "%llu", rawvalue); - else { - out+=sprintf(out, "%d", word[0]); - if (!(rawvalue==word[0])) - // The other bytes are in use. Try IBM's model - out+=sprintf(out, " (Lifetime Min/Max %d/%d)", word[1], word[2]); - } - break; - default: - out+=sprintf(out, "%llu", rawvalue); - } - - // 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, unsigned char val){ - char *name; - switch (id){ - - case 1: - name="Raw_Read_Error_Rate"; - break; - case 2: - name="Throughput_Performance"; - break; - case 3: - name="Spin_Up_Time"; - break; - case 4: - name="Start_Stop_Count"; - break; - case 5: - name="Reallocated_Sector_Ct"; - break; - case 6: - name="Read_Channel_Margin"; - break; - case 7: - name="Seek_Error_Rate"; - break; - case 8: - name="Seek_Time_Performance"; - break; - 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; - case 10: - name="Spin_Retry_Count"; - break; - case 11: - name="Calibration_Retry_Count"; - break; - case 12: - name="Power_Cycle_Count"; - break; - case 13: - name="Read_Soft_Error_Rate"; - break; - case 191: - name="G-Sense_Error_Rate"; - break; - case 192: - name="Power-Off_Retract_Count"; - break; - case 193: - name="Load_Cycle_Count"; - break; - 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; - case 195: - name="Hardware_ECC_Recovered"; - break; - case 196: - name="Reallocated_Event_Count"; - break; - case 197: - name="Current_Pending_Sector"; - break; - case 198: - name="Offline_Uncorrectable"; - break; - case 199: - name="UDMA_CRC_Error_Count"; - break; - case 200: - switch (val) { - case 1: - // Fujitsu MHS2020AT - name="Write_Error_Count"; - break; - default: - // Western Digital - name="Multi_Zone_Error_Rate"; - break; - } - break; - case 220: - switch (val) { - case 1: - name="Temperature_Celsius"; - break; - default: - name="Disk_Shift"; - break; - } - break; - case 221: - name="G-Sense_Error_Rate"; - break; - case 222: - name="Loaded_Hours"; - break; - case 223: - name="Load_Retry_Count"; - break; - case 224: - name="Load_Friction"; - break; - case 225: - name="Load_Cycle_Count"; - break; - case 226: - name="Load-in_Time"; - break; - case 227: - name="Torq-amp_Count"; - break; - case 228: - name="Power-off_Retract_Count"; - break; - case 230: - // seen in IBM DTPA-353750 - name="Head Amplitude"; - break; - case 231: - name="Temperature_Celsius"; - break; - case 240: - name="Head flying hours"; - break; - default: - name="Unknown_Attribute"; - break; - } - sprintf(out,"%3hhu %s",id,name); - return; -} diff --git a/sm5/atacmds.cpp b/sm5/atacmds.cpp deleted file mode 100644 index 50dc8484f..000000000 --- a/sm5/atacmds.cpp +++ /dev/null @@ -1,1530 +0,0 @@ -/* - * atacmds.c - * - * Home page of code is: http://smartmontools.sourceforge.net - * - * Copyright (C) 2002-3 Bruce Allen <smartmontools-support@lists.sourceforge.net> - * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org> - * Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org> - * - * 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 Software Foundation; either version 2, or (at your option) - * any later version. - * - * You should have received a copy of the GNU General Public License - * (for example COPYING); if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * This code was originally developed as a Senior Thesis by Michael Cornwell - * at the Concurrent Systems Laboratory (now part of the Storage Systems - * Research Center), Jack Baskin School of Engineering, University of - * California, Santa Cruz. http://ssrc.soe.ucsc.edu/ - * - */ - -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <stdlib.h> -#include <ctype.h> -#include "atacmds.h" -#include "utility.h" -#include "extern.h" - -const char *atacmds_c_cvsid="$Id: atacmds.cpp,v 1.98 2003/04/28 18:37:02 ballen4705 Exp $" ATACMDS_H_CVSID EXTERN_H_CVSID UTILITY_H_CVSID; - -// for passing global control variables -extern smartmonctrl *con; - -// These Drive Identity tables are taken from hdparm 5.2, and are also -// given in the ATA/ATAPI specs for the IDENTIFY DEVICE command. Note -// that SMART was first added into the ATA/ATAPI-3 Standard with -// Revision 3 of the document, July 25, 1995. Look at the "Document -// Status" revision commands at the beginning of -// http://www.t13.org/project/d2008r6.pdf to see this. -#define NOVAL_0 0x0000 -#define NOVAL_1 0xffff -/* word 81: minor version number */ -#define MINOR_MAX 0x1e -const char *minor_str[] = { /* word 81 value: */ - "Device does not report version", /* 0x0000 */ - "ATA-1 X3T9.2 781D prior to revision 4", /* 0x0001 */ - "ATA-1 published, ANSI X3.221-1994", /* 0x0002 */ - "ATA-1 X3T9.2 781D revision 4", /* 0x0003 */ - "ATA-2 published, ANSI X3.279-1996", /* 0x0004 */ - "ATA-2 X3T10 948D prior to revision 2k", /* 0x0005 */ - "ATA-3 X3T10 2008D revision 1", /* 0x0006 */ /* SMART NOT INCLUDED */ - "ATA-2 X3T10 948D revision 2k", /* 0x0007 */ - "ATA-3 X3T10 2008D revision 0", /* 0x0008 */ - "ATA-2 X3T10 948D revision 3", /* 0x0009 */ - "ATA-3 published, ANSI X3.298-199x", /* 0x000a */ - "ATA-3 X3T10 2008D revision 6", /* 0x000b */ /* 1st VERSION WITH SMART */ - "ATA-3 X3T13 2008D revision 7 and 7a", /* 0x000c */ - "ATA/ATAPI-4 X3T13 1153D revision 6", /* 0x000d */ - "ATA/ATAPI-4 T13 1153D revision 13", /* 0x000e */ - "ATA/ATAPI-4 X3T13 1153D revision 7", /* 0x000f */ - "ATA/ATAPI-4 T13 1153D revision 18", /* 0x0010 */ - "ATA/ATAPI-4 T13 1153D revision 15", /* 0x0011 */ - "ATA/ATAPI-4 published, ANSI NCITS 317-1998", /* 0x0012 */ - "ATA/ATAPI-5 T13 1321D revision 3", /* 0x0013 */ - "ATA/ATAPI-4 T13 1153D revision 14", /* 0x0014 */ - "ATA/ATAPI-5 T13 1321D revision 1", /* 0x0015 */ - "ATA/ATAPI-5 published, ANSI NCITS 340-2000", /* 0x0016 */ - "ATA/ATAPI-4 T13 1153D revision 17", /* 0x0017 */ - "ATA/ATAPI-6 T13 1410D revision 0", /* 0x0018 */ - "ATA/ATAPI-6 T13 1410D revision 3a", /* 0x0019 */ - "ATA/ATAPI-7 T13 1532D revision 1", /* 0x001a */ - "ATA/ATAPI-6 T13 1410D revision 2", /* 0x001b */ - "ATA/ATAPI-6 T13 1410D revision 1", /* 0x001c */ - "reserved", /* 0x001d */ - "ATA/ATAPI-7 T13 1532D revision 0" /* 0x001e */ -}; - -// NOTE ATA/ATAPI-4 REV 4 was the LAST revision where the device -// attribute structures were NOT completely vendor specific. So any -// disk that is ATA/ATAPI-4 or above can not be trusted to show the -// vendor values in sensible format. - -// Negative values below are because it doesn't support SMART -const int actual_ver[] = { - /* word 81 value: */ - 0, /* 0x0000 WARNING: */ - 1, /* 0x0001 WARNING: */ - 1, /* 0x0002 WARNING: */ - 1, /* 0x0003 WARNING: */ - 2, /* 0x0004 WARNING: This array */ - 2, /* 0x0005 WARNING: corresponds */ - -3, /*<== */ /* 0x0006 WARNING: *exactly* */ - 2, /* 0x0007 WARNING: to the ATA/ */ - -3, /*<== */ /* 0x0008 WARNING: ATAPI version */ - 2, /* 0x0009 WARNING: listed in */ - 3, /* 0x000a WARNING: the */ - 3, /* 0x000b WARNING: minor_str */ - 3, /* 0x000c WARNING: array */ - 4, /* 0x000d WARNING: above. */ - 4, /* 0x000e WARNING: */ - 4, /* 0x000f WARNING: If you change */ - 4, /* 0x0010 WARNING: that one, */ - 4, /* 0x0011 WARNING: change this one */ - 4, /* 0x0012 WARNING: too!!! */ - 5, /* 0x0013 WARNING: */ - 4, /* 0x0014 WARNING: */ - 5, /* 0x0015 WARNING: */ - 5, /* 0x0016 WARNING: */ - 4, /* 0x0017 WARNING: */ - 6, /* 0x0018 WARNING: */ - 6, /* 0x0019 WARNING: */ - 7, /* 0x001a WARNING: */ - 6, /* 0x001b WARNING: */ - 6, /* 0x001c WARNING: */ - 0, /* 0x001d WARNING: */ - 7 /* 0x001e WARNING: */ -}; - -// When you add additional items to this list, you should then: -// 0 -- update this list -// 1 -- modify the following function parse_attribute_def() -// 2 -- modify ataPrintSmartAttribRawValue() -// 3 - modify ataPrintSmartAttribName() -// 4 -- add #define PRESET_N_DESCRIPTION at top of knowndrives.c -// 5 -- add drive in question into knowndrives[] table in knowndrives.c -// 6 -- update smartctl.8 -// 7 -- update smartd.8 -// 8 -- do "make smartd.conf.5" to update smartd.conf.5 -// 9 -- update CHANGELOG file -const char *vendorattributeargs[] = { - // 0 defs[9]=1 - "9,minutes", - // 1 defs[9]=3 - "9,seconds", - // 2 defs[9]=2 - "9,temp", - // 3 defs[220]=1 - "220,temp", - // 4 defs[*]=253 - "N,raw8", - // 5 defs[*]=254 - "N,raw16", - // 6 defs[*]=255 - "N,raw48", - // 7 defs[200]=1 - "200,writeerrorcount", - // 8 defs[9]=4 - "9,halfminutes", - // 9 defs[194]=1 - "194,10xCelsius", - // 10 defs[194]=2 - "194,unknown", - // NULL should always terminate the array - NULL -}; - -// 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(char *pair, unsigned char *defs){ - int i,j; - char temp[32]; - - // look along list and see if we find the pair - for (i=0; vendorattributeargs[i] && strcmp(pair, vendorattributeargs[i]); i++); - - switch (i) { - case 0: - // attribute 9 is power on time in minutes - defs[9]=1; - return 0; - case 1: - // attribute 9 is power-on-time in seconds - defs[9]=3; - return 0; - case 2: - // attribute 9 is temperature in celsius - defs[9]=2; - return 0; - case 3: - // attribute 220 is temperature in celsius - defs[220]=1; - return 0; - case 4: - // print all attributes in raw 8-bit form - for (j=0; j<256; j++) - defs[j]=253; - return 0; - case 5: - // print all attributes in raw 16-bit form - for (j=0; j<256; j++) - defs[j]=254; - return 0; - case 6: - // print all attributes in raw 48-bit form - for (j=0; j<256; j++) - defs[j]=255; - return 0; - case 7: - // attribute 200 is write error count - defs[200]=1; - return 0; - case 8: - // attribute 9 increments once every 30 seconds (power on time - // measure) - defs[9]=4; - return 0; - case 9: - // attribute 194 is ten times disk temp in Celsius - defs[194]=1; - return 0; - case 10: - // attribute 194 is unknown - defs[194]=2; - return 0; - default: - // pair not found - break; - } - // At this point, either the pair was not found, or it is of the - // form N,uninterpreted, in which case we need to parse N - j=sscanf(pair,"%d,%14s", &i, temp); - - // if no match to pattern, unrecognized - if (j!=2 || i<0 || i >255) - return 1; - - // check for recognized strings - if (!strcmp(temp, "raw8")) { - defs[i]=253; - return 0; - } - - // check for recognized strings - if (!strcmp(temp, "raw16")) { - defs[i]=254; - return 0; - } - - // check for recognized strings - if (!strcmp(temp, "raw48")) { - defs[i]=255; - return 0; - } - - // didn't recognize the string - return 1; -} - -// Structure used in sorting the array vendorattributeargs[]. -typedef struct vaa_pair_s { - const char *vaa; - const char *padded_vaa; -} vaa_pair; - -// Returns a copy of s with all numbers of less than three digits padded with -// leading zeros. Returns NULL if there isn't enough memory available. The -// memory for the string is dynamically allocated and should be freed by the -// caller. -char *pad_numbers(const char *s) -{ - char c, *t, *u; - const char *r; - int i, len, ndigits = 0; - - // Allocate the maximum possible amount of memory needed. - if (!(t = (char *)malloc(strlen(s)*2+2))) - return NULL; - - // Copy the string s to t, padding any numbers of less than three digits - // with leading zeros. The string is copied backwards to simplify the code. - r = s + strlen(s); - u = t; - while (( r-- >= s)) { - if (isdigit(*r)) - ndigits++; - else if (ndigits > 0) { - while (ndigits++ < 3) - *u++ = '0'; - ndigits = 0; - } - *u++ = *r; - } - *u = '\0'; - - // Reverse the string in t. - len = strlen(t); - for (i = 0; i < len/2; i++) { - c = t[i]; - t[i] = t[len-1-i]; - t[len-1-i] = c; - } - - return t; -} - -// Comparison function for qsort(). Used by sort_vendorattributeargs(). -int compare_vaa_pairs(const void *a, const void *b) -{ - vaa_pair *p = (vaa_pair *)a; - vaa_pair *q = (vaa_pair *)b; - - return strcmp(p->padded_vaa, q->padded_vaa); -} - -// Returns a sorted list of vendorattributeargs or NULL if there is not enough -// memory available. The memory for the list is allocated dynamically and -// should be freed by the caller. -// To perform the sort, any numbers in the strings are padded out to three -// digits by adding leading zeros. For example, -// -// "9,minutes" becomes "009,minutes" -// "N,raw16" becomes "N,raw016" -// -// and the original strings are paired with the padded strings. The list of -// pairs is then sorted by comparing the padded strings (using strcmp) and the -// result is then the list of unpadded strings. -// -const char **sort_vendorattributeargs(void) { - const char **ps, **sorted_list = NULL; - vaa_pair *pairs, *pp; - int count, i; - - // Figure out how many strings are in vendorattributeargs[] (not including - // the terminating NULL). - count = (sizeof vendorattributeargs) / sizeof(char *) - 1; - - // Construct a list of pairs of strings from vendorattributeargs[] and their - // padded equivalents. - if (!(pairs = (vaa_pair *)malloc(sizeof(vaa_pair) * count))) - goto END; - for (ps = vendorattributeargs, pp = pairs; *ps; ps++, pp++) { - pp->vaa = *ps; - if (!(pp->padded_vaa = pad_numbers(*ps))) - goto END; - } - - // Sort the array of vaa_pair structures by comparing the padded strings - // using strcmp(). - qsort(pairs, count, sizeof(vaa_pair), compare_vaa_pairs); - - // Construct the sorted list of strings. - if (!(sorted_list = (const char **)malloc(sizeof vendorattributeargs))) - goto END; - for (ps = sorted_list, pp = pairs, i = 0; i < count; ps++, pp++, i++) - *ps = pp->vaa; - *ps = NULL; - -END: - if (pairs) { - for (i = 0; i < count; i++) - if (pairs[i].padded_vaa) - free((void *)pairs[i].padded_vaa); - free((void *)pairs); - } - - // If there was a problem creating the list then sorted_list should now - // contain NULL. - return sorted_list; -} - -// Function to return a multiline string containing a list of the arguments in -// vendorattributeargs[]. The strings are preceeded by tabs and followed -// (except for the last) by newlines. -// This function allocates the required memory for the string and the caller -// must use free() to free it. It returns NULL if the required memory can't -// be allocated. -char *create_vendor_attribute_arg_list(void){ - const char **ps, **sorted; - char *s; - int len; - - // Get a sorted list of vendor attribute arguments. If the sort fails - // (which should only happen if the system is really low on memory) then just - // use the unordered list. - if (!(sorted = (const char **) sort_vendorattributeargs())) - sorted = vendorattributeargs; - - // Calculate the required number of characters - len = 1; // At least one char ('\0') - for (ps = sorted; *ps != NULL; ps++) { - len += 1; // For the tab - len += strlen(*ps); // For the actual argument string - if (*(ps+1)) - len++; // For the newline if required - } - - // Attempt to allocate memory for the string - if (!(s = (char *)malloc(len))) - return NULL; - - // Construct the string - *s = '\0'; - for (ps = sorted; *ps != NULL; ps++) { - strcat(s, "\t"); - strcat(s, *ps); - if (*(ps+1)) - strcat(s, "\n"); - } - - free(sorted); - - // Return a pointer to the string - return s; -} - - -// PURPOSE -// This is an interface routine meant to isolate the OS dependent -// parts of the code, and to provide a debugging interface. Each -// different port and OS needs to provide it's own interface. This -// is the linux one. -// DETAILED DESCRIPTION OF ARGUMENTS -// device: is the file descriptor provided by open() -// command: defines the different operations. -// select: additional input data if needed (which log, which type of -// self-test). -// data: location to write output data, if needed (512 bytes). -// Note: not all commands use all arguments. -// RETURN VALUES -// -1 if the command failed -// 0 if the command succeeded, -// STATUS_CHECK routine: -// -1 if the command failed -// 0 if the command succeeded and disk SMART status is "OK" -// 1 if the command succeeded and disk SMART status is "FAILING" - - -// huge value of buffer size needed because HDIO_DRIVE_CMD assumes -// that buff[3] is the data size. Since the SMART_AUTOSAVE and -// SMART_AUTO_OFFLINE use values of 0xf1 and 0xf8 we need the space. -// Otherwise a 4+512 byte buffer would be enough. -#define STRANGE_BUFFER_LENGTH (4+512*0xf8) - -int os_specific_handler(int device, smart_command_set command, int select, char *data){ - unsigned char buff[STRANGE_BUFFER_LENGTH]; - int retval, copydata=0; - - // See struct hd_drive_cmd_hdr in hdreg.h - // buff[0]: ATA COMMAND CODE REGISTER - // buff[1]: ATA SECTOR NUMBER REGISTER - // buff[2]: ATA FEATURES REGISTER - // buff[3]: ATA SECTOR COUNT REGISTER - - // clear out buff. Large enough for HDIO_DRIVE_CMD (4+512 bytes) - memset(buff, 0, STRANGE_BUFFER_LENGTH); - - buff[0]=WIN_SMART; - switch (command){ - case READ_VALUES: - buff[2]=SMART_READ_VALUES; - copydata=buff[3]=1; - break; - case READ_THRESHOLDS: - buff[2]=SMART_READ_THRESHOLDS; - copydata=buff[1]=buff[3]=1; - break; - case READ_LOG: - buff[2]=SMART_READ_LOG_SECTOR; - buff[1]=select; - copydata=buff[3]=1; - break; - case IDENTIFY: - buff[0]=WIN_IDENTIFY; - copydata=buff[3]=1; - break; - case PIDENTIFY: - buff[0]=WIN_PIDENTIFY; - copydata=buff[3]=1; - break; - case ENABLE: - buff[2]=SMART_ENABLE; - buff[1]=1; - break; - case DISABLE: - buff[2]=SMART_DISABLE; - buff[1]=1; - break; - case STATUS: - // this command only says if SMART is working. It could be - // replaced with STATUS_CHECK below. - buff[2]=SMART_STATUS; - break; - case AUTO_OFFLINE: - buff[2]=SMART_AUTO_OFFLINE; - buff[3]=select; // YET NOTE - THIS IS A NON-DATA COMMAND!! - break; - case AUTOSAVE: - buff[2]=SMART_AUTOSAVE; - buff[3]=select; // YET NOTE - THIS IS A NON-DATA COMMAND!! - break; - case IMMEDIATE_OFFLINE: - buff[2]=SMART_IMMEDIATE_OFFLINE; - buff[1]=select; - break; - // the command uses HDIO_DRIVE_TASK and has different syntax than - // the other commands. - case STATUS_CHECK: - buff[1]=SMART_STATUS; - break; - default: - pout("Unrecognized command %d in os_specific_handler()\n", command); - exit(1); - break; - } - - // There are two different types of ioctls(). The HDIO_DRIVE_TASK - // one is this: - if (command==STATUS_CHECK){ - unsigned const char normal_lo=0x4f, normal_hi=0xc2; - unsigned const char failed_lo=0xf4, failed_hi=0x2c; - buff[4]=normal_lo; - buff[5]=normal_hi; - - // HDIO_DRIVE_TASK IOCTL -#ifdef HDIO_DRIVE_TASK - if ((retval=ioctl(device, HDIO_DRIVE_TASK, buff))) -#endif - return -1; - - // Cyl low and Cyl high unchanged means "Good SMART status" - if (buff[4]==normal_lo && buff[5]==normal_hi) - return 0; - - // These values mean "Bad SMART status" - if (buff[4]==failed_lo && buff[5]==failed_hi) - return 1; - - // We haven't gotten output that makes sense; print out some debugging info - syserror("Error SMART Status command failed"); - pout("Please get assistance from %s\n",PROJECTHOME); - pout("Register values returned from SMART Status command are:\n"); - pout("CMD=0x%02x\n",(int)buff[0]); - pout("FR =0x%02x\n",(int)buff[1]); - pout("NS =0x%02x\n",(int)buff[2]); - pout("SC =0x%02x\n",(int)buff[3]); - pout("CL =0x%02x\n",(int)buff[4]); - pout("CH =0x%02x\n",(int)buff[5]); - pout("SEL=0x%02x\n",(int)buff[6]); - return -1; - } - - // We are now doing the HDIO_DRIVE_CMD type ioctl. - if ((retval=ioctl(device, HDIO_DRIVE_CMD, buff))) - return -1; - - if (copydata) - memcpy(data, buff+4, 512); - - return 0; -} - -static char *commandstrings[]={ - [ENABLE]= "SMART ENABLE", - [DISABLE]= "SMART DISABLE", - [AUTOSAVE]= "SMART AUTOMATIC ATTRIBUTE SAVE", - [IMMEDIATE_OFFLINE]="SMART IMMEDIATE OFFLINE", - [AUTO_OFFLINE]= "SMART AUTO OFFLINE", - [STATUS]= "SMART STATUS", - [STATUS_CHECK]= "SMART STATUS CHECK", - [READ_VALUES]= "SMART READ ATTRIBUTE VALUES", - [READ_THRESHOLDS]= "SMART READ ATTRIBUTE THRESHOLDS", - [READ_LOG]= "SMART READ LOG", - [IDENTIFY]= "IDENTIFY DEVICE" , - [PIDENTIFY]= "IDENTIFY PACKET DEVICE" -}; - -void prettyprint(unsigned char *stuff, char *name){ - int i,j; - pout("\n===== [%s] DATA START (BASE-16) =====\n", name); - for (i=0; i<32; i++){ - pout("%03d-%03d: ", 16*i, 16*(i+1)-1); - for (j=0; j<15; j++) - pout("%02x ",*stuff++); - pout("%02x\n",*stuff++); - } - pout("===== [%s] DATA END (512 Bytes) =====\n\n", name); -} - -// This function provides the pretty-print reporting -int smartcommandhandler(int device, smart_command_set command, int select, char *data){ - int retval; - - // This conditional is true for commands that return data - int getsdata=(command==PIDENTIFY || - command==IDENTIFY || - command==READ_LOG || - command==READ_THRESHOLDS || - command==READ_VALUES); - - // If reporting is enabled, say what the command will be before it's executed - if (con->reportataioctl){ - // conditional is true for commands that use parameters - int usesparam=(command==READ_LOG || - command==AUTO_OFFLINE || - command==AUTOSAVE || - command==IMMEDIATE_OFFLINE); - - pout("\nREPORT-IOCTL: DeviceFD=%d Command=%s", device, commandstrings[command]); - if (usesparam) - pout(" InputParameter=%d\n", select); - else - pout("\n"); - } - - if (getsdata && data==NULL){ - pout("REPORT-IOCTL: Unable to execute command %s : data destination address is NULL\n", commandstrings[command]); - return -1; - } - - // now execute the command - retval=os_specific_handler(device, command, select, data); - - // If reporting is enabled, say what output was produced by the command - if (con->reportataioctl){ - pout("REPORT-IOCTL: DeviceFD=%d Command=%s returned %d\n", device, commandstrings[command], retval); - // if requested, pretty-print the output data structure - if (con->reportataioctl>1 && getsdata) - prettyprint((unsigned char *)data, commandstrings[command]); - } - return retval; -} - - -// This function computes the checksum of a single disk sector (512 -// bytes). Returns zero if checksum is OK, nonzero if the checksum is -// incorrect. The size (512) is correct for all SMART structures. -unsigned char checksum(unsigned char *buffer){ - unsigned char sum=0; - int i; - - for (i=0; i<512; i++) - sum+=buffer[i]; - - return sum; -} - -// Reads current Device Identity info (512 bytes) into buf -int ataReadHDIdentity (int device, struct hd_driveid *buf){ - unsigned short driveidchecksum; - - if (smartcommandhandler(device, IDENTIFY, 0, (char *)buf)){ - // See if device responds to packet command... - if (smartcommandhandler(device, PIDENTIFY, 0, (char *)buf)){ - syserror("Error ATA GET HD Identity Failed"); - return -1; - } - } - -#if 0 - // The following ifdef is a HACK to distinguish different versions - // of the header file defining hd_driveid -#ifdef CFA_REQ_EXT_ERROR_CODE - driveidchecksum=buf->integrity_word; -#else - // Note -- the declaration that appears in - // /usr/include/linux/hdreg.h: short words160_255[95], is WRONG. - // It should say: short words160_255[96]. I have written to Andre - // Hedrick about this on Oct 17 2002. Please remove this comment - // once the fix has made it into the stock kernel tree. - driveidchecksum=buf->words160_255[95]; -#endif -#else - // This way is ugly and you may feel ill -- but it always works... - { - unsigned short *rawstructure= - (unsigned short *)buf; - driveidchecksum=rawstructure[255]; - } -#endif - - if ((driveidchecksum & 0x00ff) == 0x00a5 && checksum((unsigned char *)buf)) - checksumwarning("Drive Identity Structure"); - - return 0; -} - -// Returns ATA version as an integer, and a pointer to a string -// describing which revision. Note that Revision 0 of ATA-3 does NOT -// support SMART. For this one case we return -3 rather than +3 as -// the version number. See notes above. -int ataVersionInfo (const char** description, struct hd_driveid *drive, unsigned short *minor){ - unsigned short major; - int i; - - // check that arrays at the top of this file are defined - // consistently - if (sizeof(minor_str) != sizeof(char *)*(1+MINOR_MAX)){ - pout("Internal error in ataVersionInfo(). minor_str[] size %d\n" - "is not consistent with value of MINOR_MAX+1 = %d\n", - sizeof(minor_str)/sizeof(char *), MINOR_MAX+1); - fflush(NULL); - abort(); - } - if (sizeof(actual_ver) != sizeof(int)*(1+MINOR_MAX)){ - pout("Internal error in ataVersionInfo(). actual_ver[] size %d\n" - "is not consistent with value of MINOR_MAX = %d\n", - sizeof(actual_ver)/sizeof(int), MINOR_MAX+1); - fflush(NULL); - abort(); - } - - // get major and minor ATA revision numbers -#ifdef __NEW_HD_DRIVE_ID - major=drive->major_rev_num; - *minor=drive->minor_rev_num; -#else - major=drive->word80; - *minor=drive->word81; -#endif - - // First check if device has ANY ATA version information in it - if (major==NOVAL_0 || major==NOVAL_1) { - *description=NULL; - return -1; - } - - // The minor revision number has more information - try there first - if (*minor && (*minor<=MINOR_MAX)){ - int std = actual_ver[*minor]; - if (std) { - *description=minor_str[*minor]; - return std; - } - } - - // HDPARM has a very complicated algorithm from here on. Since SMART only - // exists on ATA-3 and later standards, let's punt on this. If you don't - // like it, please fix it. The code's in CVS. - for (i=15; i>0; i--) - if (major & (0x1<<i)) - break; - - *description=NULL; - if (i==0) - return 1; - else - return i;; -} - -// returns 1 if SMART supported, 0 if not supported or can't tell -int ataSmartSupport(struct hd_driveid *drive){ - unsigned short word82,word83; - - // get correct bits of IDENTIFY DEVICE structure -#ifdef __NEW_HD_DRIVE_ID - word82=drive->command_set_1; - word83=drive->command_set_2; -#else - word82=drive->command_sets; - word83=drive->word83; -#endif - - // Note this does not work for ATA3 < Revision 6, when word82 and word83 were added - // we should check for ATA3 Rev 0 in minor identity code... - return (word83 & 0x0001<<14) && !(word83 & 0x0001<<15) && (word82 & 0x0001); -} - -// returns 1 if SMART enabled, 0 if SMART disabled, -1 if can't tell -int ataIsSmartEnabled(struct hd_driveid *drive){ - unsigned short word85,word87; - - // Get correct bits of IDENTIFY DRIVE structure -#ifdef __NEW_HD_DRIVE_ID - word85=drive->cfs_enable_1; - word87=drive->csf_default; -#else - word85=drive->word85; - word87=drive->word87; -#endif - - if ((word87 & 0x0001<<14) && !(word87 & 0x0001<<15)) - // word85 contains valid information, so - return word85 & 0x0001; - - // Since we can't rely word85, we don't know if SMART is enabled. - return -1; -} - - -// Reads SMART attributes into *data -int ataReadSmartValues(int device, struct ata_smart_values *data){ - - if (smartcommandhandler(device, READ_VALUES, 0, (char *)data)){ - syserror("Error SMART Values Read failed"); - return -1; - } - - // compute checksum - if (checksum((unsigned char *)data)) - checksumwarning("SMART Attribute Data Structure"); - - return 0; -} - -// swap two bytes. Point to low address -void swap2(char *location){ - char tmp=*location; - *location=*(location+1); - *(location+1)=tmp; - return; -} - -// swap four bytes. Point to low address -void swap4(char *location){ - char tmp=*location; - *location=*(location+3); - *(location+3)=tmp; - swap2(location+1); - return; -} - -// This corrects some quantities that are byte reversed in the SMART -// SELF TEST LOG -void fixsamsungselftestlog(struct ata_smart_selftestlog *data){ - int i; - - // swap with one byte of reserved - swap2((char *)&(data->mostrecenttest)); - - // LBA low register (here called 'selftestnumber") is byte swapped - // with Self-test execution status byte. - for (i=0; i<21; i++) - swap2((char *)&(data->selftest_struct[i].selftestnumber)); - - return; -} - -// Reads the Self Test Log (log #6) -int ataReadSelfTestLog (int device, struct ata_smart_selftestlog *data){ - - // get data from device - if (smartcommandhandler(device, READ_LOG, 0x06, (char *)data)){ - syserror("Error SMART Error Self-Test Log Read failed"); - return -1; - } - - // compute its checksum, and issue a warning if needed - if (checksum((unsigned char *)data)) - checksumwarning("SMART Self-Test Log Structure"); - - // fix firmware bugs in self-test log - if (con->fixfirmwarebug == FIX_SAMSUNG) - fixsamsungselftestlog(data); - - return 0; -} - - -// Reads the Log Directory (log #0). Note: NO CHECKSUM!! -int ataReadLogDirectory (int device, struct ata_smart_log_directory *data){ - - // get data from device - if (smartcommandhandler(device, READ_LOG, 0x00, (char *)data)){ - return -1; - } - return 0; -} - -// This corrects some quantities that are byte reversed in the SMART -// ATA ERROR LOG -void fixsamsungerrorlog(struct ata_smart_errorlog *data){ - int i,j; - - // Device error count in bytes 452-3 - swap2((char *)&(data->ata_error_count)); - - // step through 5 error log data structures - for (i=0; i<5; i++){ - // step through 5 command data structures - for (j=0; j<5; j++) - // Command data structure 4-byte millisec timestamp - swap4((char *)&(data->errorlog_struct[i].commands[j].timestamp)); - // Error data structure life timestamp - swap2((char *)&(data->errorlog_struct[i].error_struct.timestamp)); - } -} - -// Reads the Error Log (log #1) -int ataReadErrorLog (int device, struct ata_smart_errorlog *data){ - - // get data from device - if (smartcommandhandler(device, READ_LOG, 0x01, (char *)data)){ - syserror("Error SMART Error Log Read failed"); - return -1; - } - - // compute its checksum, and issue a warning if needed - if (checksum((unsigned char *)data)) - checksumwarning("SMART ATA Error Log Structure"); - - // Some disks have the byte order reversed in some SMART Summary - // Error log entries - if (con->fixfirmwarebug == FIX_SAMSUNG) - fixsamsungerrorlog(data); - - return 0; -} - -int ataReadSmartThresholds (int device, struct ata_smart_thresholds *data){ - - // get data from device - if (smartcommandhandler(device, READ_THRESHOLDS, 0, (char *)data)){ - syserror("Error SMART Thresholds Read failed"); - return -1; - } - - // compute its checksum, and issue a warning if needed - if (checksum((unsigned char *)data)) - checksumwarning("SMART Attribute Thresholds Structure"); - - return 0; -} - -int ataEnableSmart (int device ){ - if (smartcommandhandler(device, ENABLE, 0, NULL)){ - syserror("Error SMART Enable failed"); - return -1; - } - return 0; -} - -int ataDisableSmart (int device ){ - - if (smartcommandhandler(device, DISABLE, 0, NULL)){ - syserror("Error SMART Disable failed"); - return -1; - } - return 0; -} - -int ataEnableAutoSave(int device){ - if (smartcommandhandler(device, AUTOSAVE, 241, NULL)){ - syserror("Error SMART Enable Auto-save failed"); - return -1; - } - return 0; -} - -int ataDisableAutoSave(int device){ - - if (smartcommandhandler(device, AUTOSAVE, 0, NULL)){ - syserror("Error SMART Disable Auto-save failed"); - return -1; - } - return 0; -} - -// Note that in the ATA-5 standard the Enable/Disable AutoOffline -// command is marked "OBSOLETE". Curiously, I could not find it -// documented in ANY of the ATA specifications. In other words, it's -// been obsolete forever. However some vendors (eg, IBM) seem to be -// using this command anyway. For example see the IBM Travelstar -// 40GNX hard disk drive specifications page 164 Revision 1.1 22 Apr -// 2002. This gives a detailed description of the command, although -// the drive claims to comply with the ATA/ATAPI-5 Revision 3 -// standard! The latter document makes no mention of this command at -// all, other than to say that it is "obsolete". -int ataEnableAutoOffline (int device ){ - - /* timer hard coded to 4 hours */ - if (smartcommandhandler(device, AUTO_OFFLINE, 248, NULL)){ - syserror("Error SMART Enable Automatic Offline failed"); - return -1; - } - return 0; -} - -// Another Obsolete Command. See comments directly above, associated -// with the corresponding Enable command. -int ataDisableAutoOffline (int device ){ - - if (smartcommandhandler(device, AUTO_OFFLINE, 0, NULL)){ - syserror("Error SMART Disable Automatic Offline failed"); - return -1; - } - return 0; -} - - -// This function does NOTHING except tell us if SMART is working & -// enabled on the device. See ataSmartStatus2() for one that actually -// returns SMART status. -int ataSmartStatus (int device ){ - - if (smartcommandhandler(device, STATUS, 0, NULL)){ - syserror("Error Return SMART Status via HDIO_DRIVE_CMD failed"); - return -1; - } - return 0; -} - -// If SMART is enabled, supported, and working, then this call is -// guaranteed to return 1, else zero. Silent inverse of -// ataSmartStatus() -int ataDoesSmartWork(int device){ - return !smartcommandhandler(device, STATUS, 0, NULL); -} - -#ifdef HDIO_DRIVE_TASK -// This function uses a different interface (DRIVE_TASK) than the -// other commands in this file. -int ataSmartStatus2(int device){ - - int returnval=smartcommandhandler(device, STATUS_CHECK, 0, NULL); - - if (returnval==-1){ - syserror("Error SMART Status command via HDIO_DRIVE_TASK failed"); - pout("Rebuild older linux 2.2 kernels with HDIO_DRIVE_TASK support enabled\n"); - } - - return returnval; -} -#else -// Just a hack so that the code compiles on -// 2.2 kernels without HDIO_DRIVE TASK support. -// Should be fixed by putting in a call to code -// that compares smart data to thresholds. -int ataSmartStatus2(int device){ - pout("This code was compiled on a machine whose kernel header\n" - "files do not support the HDIO_DRIVE_TASK ioctl().\n" - "Compile on a linux 2.2 kernel box with HDIO_DRIVE_TASK\n" - "support enabled, or on a 2.4 kernel box, please.\n"); - return ataSmartStatus(device); -} -#endif - - -// This is the way to execute ALL tests: offline, short self-test, -// extended self test, with and without captive mode, etc. -int ataSmartTest(int device, int testtype){ - char cmdmsg[128],*type,*captive; - int errornum; - int cap; - - // Boolean, if set, says test is captive - cap=testtype & CAPTIVE_MASK; - - // Set up strings that describe the type of test - if (cap) - captive="captive"; - else - captive="off-line"; - - if (testtype==OFFLINE_FULL_SCAN) - type="off-line"; - else if (testtype==SHORT_SELF_TEST || testtype==SHORT_CAPTIVE_SELF_TEST) - type="Short self-test"; - else if (testtype==EXTEND_SELF_TEST || testtype==EXTEND_CAPTIVE_SELF_TEST) - type="Extended self-test"; - else if (testtype==CONVEYANCE_SELF_TEST || testtype==CONVEYANCE_CAPTIVE_SELF_TEST) - type="Conveyance self-test"; - else if (testtype==SELECTIVE_SELF_TEST || testtype==SELECTIVE_CAPTIVE_SELF_TEST) - type="Selective self-test"; - else - type="[Unrecognized] self-test"; - - // Print ouf message that we are sending the command to test - if (testtype==ABORT_SELF_TEST) - sprintf(cmdmsg,"Abort SMART off-line mode self-test routine"); - else - sprintf(cmdmsg,"Execute SMART %s routine immediately in %s mode",type,captive); - pout("Sending command: \"%s\".\n",cmdmsg); - - // Now send the command to test - errornum=smartcommandhandler(device, IMMEDIATE_OFFLINE, testtype, NULL); - - if (errornum && !(cap && errno==EIO)){ - char errormsg[128]; - sprintf(errormsg,"Command \"%s\" failed",cmdmsg); - syserror(errormsg); - pout("\n"); - return -1; - } - - // Since the command succeeded, tell user - if (testtype==ABORT_SELF_TEST) - pout("Self-testing aborted!\n"); - else - pout("Drive command \"%s\" successful.\nTesting has begun.\n",cmdmsg); - return 0; -} - -/* Test Time Functions */ -int TestTime(struct ata_smart_values *data,int testtype){ - switch (testtype){ - case OFFLINE_FULL_SCAN: - return (int) data->total_time_to_complete_off_line; - case SHORT_SELF_TEST: - case SHORT_CAPTIVE_SELF_TEST: - return (int) data->short_test_completion_time; - case EXTEND_SELF_TEST: - case EXTEND_CAPTIVE_SELF_TEST: - return (int) data->extend_test_completion_time; - default: - return 0; - } -} - -// This function tells you both about the ATA error log and the -// self-test error log capability. The bit is poorly documented in -// the ATA/ATAPI standard. -int isSmartErrorLogCapable ( struct ata_smart_values *data){ - return data->errorlog_capability & 0x01; -} -int isSupportExecuteOfflineImmediate(struct ata_smart_values *data){ - return data->offline_data_collection_capability & 0x01; -} - -int isGeneralPurposeLoggingCapable(struct hd_driveid *identity){ - unsigned short *rawwords=(unsigned short *)identity; - unsigned short word84, word87; - - word84=rawwords[84]; - word87=rawwords[87]; - - // If bit 14 of word 84 is set to one and bit 15 of word 84 is - // cleared to zero, the contents of word 84 contains valid support - // information. If not, support information is not valid in this - // word. - if ((word84>>14) == 0x01) - // If bit 5 of word 84 is set to one, the device supports the - // General Purpose Logging feature set. - return (word84 & (0x01 << 5)); - - // If bit 14 of word 87 is set to one and bit 15 of word 87 is - // cleared to zero, the contents of words (87:85) contain valid - // information. If not, information is not valid in these words. - if ((word87>>14) == 0x01) - // If bit 5 of word 87 is set to one, the device supports - // the General Purpose Logging feature set. - return (word87 & (0x01 << 5)); - - // not capable - return 0; -} - - -// Note in the ATA-5 standard, the following bit is listed as "Vendor -// Specific". So it may not be reliable. The only use of this that I -// have found is in IBM drives, where it is well-documented. See for -// example page 170, section 13.32.1.18 of the IBM Travelstar 40GNX -// hard disk drive specifications page 164 Revision 1.1 22 Apr 2002. -int isSupportAutomaticTimer(struct ata_smart_values *data){ - return data->offline_data_collection_capability & 0x02; -} -int isSupportOfflineAbort(struct ata_smart_values *data){ - return data->offline_data_collection_capability & 0x04; -} -int isSupportOfflineSurfaceScan(struct ata_smart_values *data){ - return data->offline_data_collection_capability & 0x08; -} -int isSupportSelfTest (struct ata_smart_values *data){ - return data->offline_data_collection_capability & 0x10; -} -int isSupportConveyanceSelfTest(struct ata_smart_values *data){ - return data->offline_data_collection_capability & 0x20; -} -int isSupportSelectiveSelfTest(struct ata_smart_values *data){ - return data->offline_data_collection_capability & 0x40; -} - - - -// 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(struct ata_smart_values *data, - struct ata_smart_thresholds *thresholds, - int onlyfailed){ - int i; - - // loop over all attributes - for (i=0; i<NUMBER_ATA_SMART_ATTRIBUTES; i++){ - - // pointers to disk's values and vendor's thresholds - struct ata_smart_attribute *disk=data->vendor_attributes+i; - struct 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 && disk->status.flag.prefailure) - return disk->id; - } - } - return 0; -} - - - -// 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(struct ata_smart_values *data, - struct ata_smart_thresholds *thresholds, - int n){ - struct ata_smart_attribute *disk; - struct ata_smart_threshold_entry *thre; - - if (n<0 || n>=NUMBER_ATA_SMART_ATTRIBUTES || !data || !thresholds) - return 0; - - // pointers to disk's values and vendor's thresholds - disk=data->vendor_attributes+n; - thre=thresholds->thres_entries+n; - - 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 (disk->status.flag.prefailure) - return disk->id; - else - return -1*(disk->id); -} - - -// 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. - -long long ataPrintSmartAttribRawValue(char *out, - struct ata_smart_attribute *attribute, - unsigned char *defs){ - long long rawvalue; - unsigned word[3]; - int j; - - // 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. - long long 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]; - } - - // Print six one-byte quantities. - if (defs[attribute->id]==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 (defs[attribute->id]==254){ - out+=sprintf(out, "%d %d %d", word[2], word[1], word[0]); - return rawvalue; - } - - // Print one six-byte quantity - if (defs[attribute->id]==255){ - out+=sprintf(out, "%llu", rawvalue); - return rawvalue; - } - - // 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]); - break; - // Power on time - case 9: - if (defs[9]==1){ - // minutes - long long tmp1=rawvalue/60; - long long tmp2=rawvalue%60; - out+=sprintf(out, "%lluh+%02llum", tmp1, tmp2); - } - else if (defs[9]==3){ - // seconds - long long hours=rawvalue/3600; - long long minutes=(rawvalue-3600*hours)/60; - long long seconds=rawvalue%60; - out+=sprintf(out, "%lluh+%02llum+%02llus", hours, minutes, seconds); - } - else if (defs[9]==4){ - // 30-second counter - long long tmp1=rawvalue/120; - long long tmp2=(rawvalue-120*tmp1)/2; - out+=sprintf(out, "%lluh+%02llum", tmp1, tmp2); - } - else - // hours - out+=sprintf(out, "%llu", rawvalue); //stored in hours - break; - // Temperature - case 194: - if (defs[194]==1){ - // ten times temperature in Celsius - int deg=word[0]/10; - int tenths=word[0]%10; - out+=sprintf(out, "%d.%d", deg, tenths); - } - else if (defs[194]==2) - // unknown attribute - out+=sprintf(out, "%llu", rawvalue); - else { - out+=sprintf(out, "%d", word[0]); - if (!(rawvalue==word[0])) - // The other bytes are in use. Try IBM's model - out+=sprintf(out, " (Lifetime Min/Max %d/%d)", word[1], word[2]); - } - break; - default: - out+=sprintf(out, "%llu", rawvalue); - } - - // 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, unsigned char val){ - char *name; - switch (id){ - - case 1: - name="Raw_Read_Error_Rate"; - break; - case 2: - name="Throughput_Performance"; - break; - case 3: - name="Spin_Up_Time"; - break; - case 4: - name="Start_Stop_Count"; - break; - case 5: - name="Reallocated_Sector_Ct"; - break; - case 6: - name="Read_Channel_Margin"; - break; - case 7: - name="Seek_Error_Rate"; - break; - case 8: - name="Seek_Time_Performance"; - break; - 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; - case 10: - name="Spin_Retry_Count"; - break; - case 11: - name="Calibration_Retry_Count"; - break; - case 12: - name="Power_Cycle_Count"; - break; - case 13: - name="Read_Soft_Error_Rate"; - break; - case 191: - name="G-Sense_Error_Rate"; - break; - case 192: - name="Power-Off_Retract_Count"; - break; - case 193: - name="Load_Cycle_Count"; - break; - 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; - case 195: - name="Hardware_ECC_Recovered"; - break; - case 196: - name="Reallocated_Event_Count"; - break; - case 197: - name="Current_Pending_Sector"; - break; - case 198: - name="Offline_Uncorrectable"; - break; - case 199: - name="UDMA_CRC_Error_Count"; - break; - case 200: - switch (val) { - case 1: - // Fujitsu MHS2020AT - name="Write_Error_Count"; - break; - default: - // Western Digital - name="Multi_Zone_Error_Rate"; - break; - } - break; - case 220: - switch (val) { - case 1: - name="Temperature_Celsius"; - break; - default: - name="Disk_Shift"; - break; - } - break; - case 221: - name="G-Sense_Error_Rate"; - break; - case 222: - name="Loaded_Hours"; - break; - case 223: - name="Load_Retry_Count"; - break; - case 224: - name="Load_Friction"; - break; - case 225: - name="Load_Cycle_Count"; - break; - case 226: - name="Load-in_Time"; - break; - case 227: - name="Torq-amp_Count"; - break; - case 228: - name="Power-off_Retract_Count"; - break; - case 230: - // seen in IBM DTPA-353750 - name="Head Amplitude"; - break; - case 231: - name="Temperature_Celsius"; - break; - case 240: - name="Head flying hours"; - break; - default: - name="Unknown_Attribute"; - break; - } - sprintf(out,"%3hhu %s",id,name); - return; -} diff --git a/sm5/atacmds.h b/sm5/atacmds.h deleted file mode 100644 index 61176bb07..000000000 --- a/sm5/atacmds.h +++ /dev/null @@ -1,426 +0,0 @@ -/* - * atacmds.h - * - * Home page of code is: http://smartmontools.sourceforge.net - * - * Copyright (C) 2002-3 Bruce Allen <smartmontools-support@lists.sourceforge.net> - * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org> - * - * 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 Software Foundation; either version 2, or (at your option) - * any later version. - * - * You should have received a copy of the GNU General Public License - * (for example COPYING); if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * This code was originally developed as a Senior Thesis by Michael Cornwell - * at the Concurrent Systems Laboratory (now part of the Storage Systems - * Research Center), Jack Baskin School of Engineering, University of - * California, Santa Cruz. http://ssrc.soe.ucsc.edu/ - * - */ - -#ifndef _ATACMDS_H_ -#define _ATACMDS_H_ - -#ifndef ATACMDS_H_CVSID -#define ATACMDS_H_CVSID "$Id: atacmds.h,v 1.43 2003/04/18 12:37:14 ballen4705 Exp $\n" -#endif - -// These are the major and minor versions for smartd and smartctl -#define PROJECTHOME "http://smartmontools.sourceforge.net/" -#define RELEASE_MAJOR 5 -#define RELEASE_MINOR 1 - -#include <sys/ioctl.h> -#include <linux/hdreg.h> -#include <sys/fcntl.h> -#include <sys/types.h> - - -typedef enum { - // returns no data, just succeeds or fails - ENABLE, - DISABLE, - AUTOSAVE, - IMMEDIATE_OFFLINE, - AUTO_OFFLINE, - STATUS, - STATUS_CHECK, - // return 512 bytes of data: - READ_VALUES, - READ_THRESHOLDS, - READ_LOG, - IDENTIFY, - PIDENTIFY -} smart_command_set; - -/* These defines SHOULD BE in the kernel - if not we define them */ - -#ifndef WIN_SMART -#define WIN_SMART 0xb0 -#endif - -#ifndef SMART_READ_VALUES -#define SMART_READ_VALUES 0xd0 -#endif - -#ifndef SMART_READ_THRESHOLDS -#define SMART_READ_THRESHOLDS 0xd1 -#endif - -#ifndef SMART_AUTOSAVE -#define SMART_AUTOSAVE 0xd2 -#endif - -#ifndef SMART_SAVE -#define SMART_SAVE 0xd3 -#endif - -#ifndef SMART_IMMEDIATE_OFFLINE -#define SMART_IMMEDIATE_OFFLINE 0xd4 -#endif - -#ifndef SMART_READ_LOG_SECTOR -#define SMART_READ_LOG_SECTOR 0xd5 -#endif - -#ifndef SMART_WRITE_LOG_SECTOR -#define SMART_WRITE_LOG_SECTOR 0xd6 -#endif - -// The following is obsolete -- don't use it! -#ifndef SMART_WRITE_THRESHOLDS -#define SMART_WRITE_THRESHOLDS 0xd7 -#endif - - -#ifndef SMART_ENABLE -#define SMART_ENABLE 0xd8 -#endif - -#ifndef SMART_DISABLE -#define SMART_DISABLE 0xd9 -#endif - -#ifndef SMART_STATUS -#define SMART_STATUS 0xda -#endif - -// The following is also marked obsolete in ATA-5 -#ifndef SMART_AUTO_OFFLINE -#define SMART_AUTO_OFFLINE 0xdb -#endif - -#define OFFLINE_FULL_SCAN 0 -#define SHORT_SELF_TEST 1 -#define EXTEND_SELF_TEST 2 -#define CONVEYANCE_SELF_TEST 3 -#define SELECTIVE_SELF_TEST 4 -#define ABORT_SELF_TEST 127 -#define SHORT_CAPTIVE_SELF_TEST 129 -#define EXTEND_CAPTIVE_SELF_TEST 130 -#define CONVEYANCE_CAPTIVE_SELF_TEST 131 -#define SELECTIVE_CAPTIVE_SELF_TEST 132 -#define CAPTIVE_MASK (0x01<<7) - -#define NUMBER_ATA_SMART_ATTRIBUTES 30 - -#define ATA_SMART_SEC_SIZE 512 - -#ifndef HDIO_DRIVE_CMD_HDR_SIZE -#define HDIO_DRIVE_CMD_HDR_SIZE 4 -#endif - -#ifndef HDIO_DRIVE_TASK_HDR_SIZE -#define HDIO_DRIVE_TASK_HDR_SIZE 7 -#endif - -/* ata_smart_attribute is the vendor specific in SFF-8035 spec */ -struct ata_smart_attribute { - unsigned char id; - union { - unsigned short all; - struct { - unsigned prefailure:1; // 0=> low attribute from age/usage - // exceeding design limit, - // 1==prefailure - - unsigned online:1; // 0==> attribute only updated during - // off-line testing. 1==>only updated - // during on-line testing - unsigned performance:1; - unsigned errorrate:1; - unsigned eventcount:1 ; - unsigned selfperserving:1; - unsigned reserved:10; - } __attribute__ ((packed)) flag; - } status ; - unsigned char current; - unsigned char worst; - unsigned char raw[6]; - unsigned char reserv; -} __attribute__ ((packed)); - - -// What follows is the ATA/ATAPI-4 Rev 13 data structure equivalent: -// Table 23 DEVICE SMART DATA STRUCTURE -#if 0 -struct ata_smart_values { - unsigned short int revnumber; - struct ata_smart_attribute vendor_attributes [NUMBER_ATA_SMART_ATTRIBUTES]; - unsigned char offline_data_collection_status; - unsigned char vendor_specific_363; //IBM # segments for offline collection - unsigned short int total_time_to_complete_off_line; // IBM different - unsigned char vendor_specific_366; // IBM curent segment pointer - unsigned char offline_data_collection_capability; - unsigned short int smart_capability; - unsigned char reserved_370_385;; - unsigned char vendor_specific_386-510; // IBM: self-test failure checkpoint - unsigned char chksum; -} __attribute__ ((packed)); -#endif - - -/* ata_smart_values is format of the read drive Attribute command */ -/* see Table 34 of T13/1321D Rev 1 spec (Device SMART data structure) for *some* info */ -struct ata_smart_values { - unsigned short int revnumber; - struct ata_smart_attribute vendor_attributes [NUMBER_ATA_SMART_ATTRIBUTES]; - unsigned char offline_data_collection_status; - unsigned char self_test_exec_status; //IBM # segments for offline collection - unsigned short int total_time_to_complete_off_line; // IBM different - unsigned char vendor_specific_366; // IBM curent segment pointer - unsigned char offline_data_collection_capability; - unsigned short int smart_capability; - unsigned char errorlog_capability; - unsigned char vendor_specific_371; // IBM: self-test failure checkpoint - unsigned char short_test_completion_time; - unsigned char extend_test_completion_time; - unsigned char conveyance_test_completion_time; - unsigned char reserved_375_385[11]; - unsigned char vendor_specific_386_510[125]; - unsigned char chksum; -} __attribute__ ((packed)); - -/* Smart Threshold data structures */ - -/* Vendor attribute of SMART Threshold (compare to ata_smart_attribute above) */ -struct ata_smart_threshold_entry { - unsigned char id; - unsigned char threshold; - unsigned char reserved[10]; -} __attribute__ ((packed)); - - -/* Format of Read SMART THreshold Command */ -/* Compare to ata_smart_values above */ -struct ata_smart_thresholds { - unsigned short int revnumber; - struct ata_smart_threshold_entry thres_entries[NUMBER_ATA_SMART_ATTRIBUTES]; - unsigned char reserved[149]; - unsigned char chksum; -} __attribute__ ((packed)); - - -// Table 42 of T13/1321D Rev 1 spec (Error Data Structure) -struct ata_smart_errorlog_error_struct { - unsigned char reserved; - unsigned char error_register; - unsigned char sector_count; - unsigned char sector_number; - unsigned char cylinder_low; - unsigned char cylinder_high; - unsigned char drive_head; - unsigned char status; - unsigned char extended_error[19]; - unsigned char state; - unsigned short timestamp; -} __attribute__ ((packed)); - -// Table 41 of T13/1321D Rev 1 spec (Command Data Structure) -struct ata_smart_errorlog_command_struct { - unsigned char devicecontrolreg; - unsigned char featuresreg; - unsigned char sector_count; - unsigned char sector_number; - unsigned char cylinder_low; - unsigned char cylinder_high; - unsigned char drive_head; - unsigned char commandreg; - unsigned int timestamp; -} __attribute__ ((packed)); - -// Table 40 of T13/1321D Rev 1 spec (Error log data structure) -struct ata_smart_errorlog_struct { - struct ata_smart_errorlog_command_struct commands[5]; - struct ata_smart_errorlog_error_struct error_struct; -} __attribute__ ((packed)); - -// Table 39 of T13/1321D Rev 1 spec (SMART error log sector) -struct ata_smart_errorlog { - unsigned char revnumber; - unsigned char error_log_pointer; - struct ata_smart_errorlog_struct errorlog_struct[5]; - unsigned short int ata_error_count; - unsigned char reserved[57]; - unsigned char checksum; -} __attribute__ ((packed)); - -// Table 45 of T13/1321D Rev 1 spec (Self-test log descriptor entry) -struct ata_smart_selftestlog_struct { - unsigned char selftestnumber; // Sector number register - unsigned char selfteststatus; - unsigned short int timestamp; - unsigned char selftestfailurecheckpoint; - unsigned int lbafirstfailure; - unsigned char vendorspecific[15]; -} __attribute__ ((packed)); - -// Table 44 of T13/1321D Rev 1 spec (Self-test log data structure) -struct ata_smart_selftestlog { - unsigned short int revnumber; - struct ata_smart_selftestlog_struct selftest_struct[21]; - unsigned char vendorspecific[2]; - unsigned char mostrecenttest; - unsigned char reserved[2]; - unsigned char chksum; -} __attribute__ ((packed)); - - - -// SMART LOG DIRECTORY Table 52 of T13/1532D Vol 1 Rev 1a -struct ata_smart_log_entry { - unsigned char numsectors; - unsigned char reserved; -} __attribute__ ((packed)); - -struct ata_smart_log_directory { - unsigned short int logversion; - struct ata_smart_log_entry entry[255]; -} __attribute__ ((packed)); - - -/* Read S.M.A.R.T information from drive */ -int ataReadHDIdentity(int device, struct hd_driveid *buf); -int ataReadSmartValues(int device,struct ata_smart_values *); -int ataReadSmartThresholds(int device, struct ata_smart_thresholds *); -int ataReadErrorLog(int device, struct ata_smart_errorlog *); -int ataReadSelfTestLog(int device, struct ata_smart_selftestlog *); -int ataSmartStatus(int device); -int ataSetSmartThresholds(int device, struct ata_smart_thresholds *); -int ataReadLogDirectory(int device, struct ata_smart_log_directory *); - -/* Enable/Disable SMART on device */ -int ataEnableSmart ( int device ); -int ataDisableSmart (int device ); -int ataEnableAutoSave(int device); -int ataDisableAutoSave(int device); - -/* Automatic Offline Testing */ -int ataEnableAutoOffline ( int device ); -int ataDisableAutoOffline (int device ); - -/* S.M.A.R.T. test commands */ -int ataSmartOfflineTest (int device); -int ataSmartExtendSelfTest (int device); -int ataSmartShortSelfTest (int device); -int ataSmartShortCapSelfTest (int device); -int ataSmartExtendCapSelfTest (int device); -int ataSmartSelfTestAbort (int device); - -// Returns the latest compatibility of ATA/ATAPI Version the device -// supports. Returns -1 if Version command is not supported -int ataVersionInfo (const char **description, struct hd_driveid *drive, unsigned short *minor); - -// If SMART supported, this is guaranteed to return 1 if SMART is enabled, else 0. -int ataDoesSmartWork(int device); - -// returns 1 if SMART supported, 0 if not supported or can't tell -int ataSmartSupport ( struct hd_driveid *drive); - -// Return values: -// 1: SMART enabled -// 0: SMART disabled -// -1: can't tell if SMART is enabled -- try issuing ataDoesSmartWork command to see -int ataIsSmartEnabled(struct hd_driveid *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 ( struct ata_smart_values *data, struct ata_smart_thresholds *thresholds, int onlyfailed); - -int ataSmartStatus2(int device); - -// int isOfflineTestTime ( struct ata_smart_values data) -// returns S.M.A.R.T. Offline Test Time in seconds -int isOfflineTestTime ( struct ata_smart_values *data); - -int isShortSelfTestTime ( struct ata_smart_values *data); - -int isExtendedSelfTestTime ( struct ata_smart_values *data); - -int isSmartErrorLogCapable ( struct ata_smart_values *data); - -int isGeneralPurposeLoggingCapable(struct hd_driveid *identity); - -int isSupportExecuteOfflineImmediate ( struct ata_smart_values *data); - -int isSupportAutomaticTimer ( struct ata_smart_values *data); - -int isSupportOfflineAbort ( struct ata_smart_values *data); - -int isSupportOfflineSurfaceScan ( struct ata_smart_values *data); - -int isSupportSelfTest (struct ata_smart_values *data); - -int isSupportConveyanceSelfTest(struct ata_smart_values *data); - -int isSupportSelectiveSelfTest(struct ata_smart_values *data); - -int ataSmartTest(int device, int testtype); - -int TestTime(struct ata_smart_values *data,int testtype); - -// Prints the raw value (with appropriate formatting) into the -// character string out. -long long ataPrintSmartAttribRawValue(char *out, - struct ata_smart_attribute *attribute, - unsigned char *defs); - -// Prints Attribute Name for standard SMART attributes. Writes a -// 30 byte string with attribute name into output -void ataPrintSmartAttribName(char *output, unsigned char id, unsigned char val); - -// 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(struct ata_smart_values *data, - struct ata_smart_thresholds *thresholds, - int n); - -// External handler function, for when a checksum is not correct. Can -// simply return if no action is desired, or can print error messages -// as needed, or exit. Is passed a string with the name of the Data -// Structure with the incorrect checksum. -void checksumwarning(const char *string); - -extern const char *vendorattributeargs[]; - -// 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(char *pair, unsigned char *defs); - -// Function to return a string containing a list of the arguments in -// vendorattributeargs[]. Returns NULL if the required memory can't -// be allocated. -char *create_vendor_attribute_arg_list(void); - -#endif /* _ATACMDS_H_ */ diff --git a/sm5/ataprint.c b/sm5/ataprint.c deleted file mode 100644 index a8a279e0f..000000000 --- a/sm5/ataprint.c +++ /dev/null @@ -1,1225 +0,0 @@ -/* - * ataprint.c - * - * Home page of code is: http://smartmontools.sourceforge.net - * - * Copyright (C) 2002-3 Bruce Allen <smartmontools-support@lists.sourceforge.net> - * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org> - * - * 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 Software Foundation; either version 2, or (at your option) - * any later version. - * - * You should have received a copy of the GNU General Public License - * (for example COPYING); if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * This code was originally developed as a Senior Thesis by Michael Cornwell - * at the Concurrent Systems Laboratory (now part of the Storage Systems - * Research Center), Jack Baskin School of Engineering, University of - * California, Santa Cruz. http://ssrc.soe.ucsc.edu/ - * - */ - -#include <ctype.h> -#include <stdio.h> -#include <syslog.h> -#include <string.h> -#include "atacmds.h" -#include "ataprint.h" -#include "smartctl.h" -#include "extern.h" -#include "utility.h" -#include "knowndrives.h" - -const char *ataprint_c_cvsid="$Id: ataprint.c,v 1.85 2003/04/25 22:31:41 ballen4705 Exp $" -ATACMDS_H_CVSID ATAPRINT_H_CVSID EXTERN_H_CVSID KNOWNDRIVES_H_CVSID SMARTCTL_H_CVSID UTILITY_H_CVSID; - -// for passing global control variables -extern smartmonctrl *con; - -// Copies n bytes (or n-1 if n is odd) from in to out, but swaps adjacents -// bytes. -void swapbytes(char *out, const char *in, size_t n) -{ - size_t i; - - for (i = 0; i < n; i += 2) { - out[i] = in[i+1]; - out[i+1] = in[i]; - } -} - -// Copies in to out, but removes leading and trailing whitespace. -void trim(char *out, const char *in) -{ - int i, first, last; - - // Find the first non-space character (maybe none). - first = -1; - for (i = 0; in[i]; i++) - if (!isspace(in[i])) { - first = i; - break; - } - - if (first == -1) { - // There are no non-space characters. - out[0] = '\0'; - return; - } - - // Find the last non-space character. - for (i = strlen(in)-1; i >= first && isspace(in[i]); i--) - ; - last = i; - - strncpy(out, in+first, last-first+1); - out[last-first+1] = '\0'; -} - -// Convenience function for formatting strings from hd_driveid. -void formatdriveidstring(char *out, const char *in, int n) -{ - char tmp[65]; - - n = n > 64 ? 64 : n; - swapbytes(tmp, in, n); - tmp[n] = '\0'; - trim(out, tmp); -} - -// Function for printing ASCII byte-swapped strings, skipping white -// space. This is needed on little-endian architectures, eg Intel, -// Alpha. If someone wants to run this on SPARC they'll need to test -// for the Endian-ness and skip the byte swapping if it's big-endian. -void printswap(char *output, char *in, unsigned int n){ - formatdriveidstring(output, in, n); - if (*output) - pout("%s\n", output); - else - pout("[No Information Found]\n"); -} - -void ataPrintDriveInfo (struct hd_driveid *drive){ - int version, drivetype; - const char *description; - char unknown[64], timedatetz[64]; - unsigned short minorrev; - char model[64], serial[64], firm[64]; - - - // print out model, serial # and firmware versions (byte-swap ASCI strings) - pout("Device Model: "); - printswap(model, drive->model,40); - - pout("Serial Number: "); - printswap(serial, drive->serial_no,20); - - pout("Firmware Version: "); - printswap(firm, drive->fw_rev,8); - - // See if drive is recognized - drivetype=lookupdrive(model, firm); - pout("Device is: %s\n", drivetype<0? - "Not in smartctl database [for details use: -P showall]": - "In smartctl database [for details use: -P show]"); - - // now get ATA version info - version=ataVersionInfo(&description,drive, &minorrev); - - // unrecognized minor revision code - if (!description){ - if (!minorrev) - sprintf(unknown, "Exact ATA specification draft version not indicated"); - else - sprintf(unknown,"Not recognized. Minor revision code: 0x%02hx", minorrev); - description=unknown; - } - - - // SMART Support was first added into the ATA/ATAPI-3 Standard with - // Revision 3 of the document, July 25, 1995. Look at the "Document - // Status" revision commands at the beginning of - // http://www.t13.org/project/d2008r6.pdf to see this. So it's not - // enough to check if we are ATA-3. Version=-3 indicates ATA-3 - // BEFORE Revision 3. - pout("ATA Version is: %d\n",(int)abs(version)); - pout("ATA Standard is: %s\n",description); - - // print current time and date and timezone - dateandtimezone(timedatetz); - pout("Local Time is: %s\n", timedatetz); - - // Print warning message, if there is one - if (drivetype>=0 && knowndrives[drivetype].warningmsg) - pout("\n==> WARNING: %s\n\n", knowndrives[drivetype].warningmsg); - - if (version>=3) - return; - - pout("SMART is only available in ATA Version 3 Revision 3 or greater.\n"); - pout("We will try to proceed in spite of this.\n"); - return; -} - - -/* prints verbose value Off-line data collection status byte */ -void PrintSmartOfflineStatus(struct ata_smart_values *data){ - - pout("Off-line data collection status: "); - - switch(data->offline_data_collection_status){ - case 0x00: - case 0x80: - pout("(0x%02x)\tOffline data collection activity was\n\t\t\t\t\t", - (int)data->offline_data_collection_status); - pout("never started.\n"); - break; - case 0x01: - case 0x81: - pout("(0x%02x)\tReserved.\n", - (int)data->offline_data_collection_status); - break; - case 0x02: - case 0x82: - pout("(0x%02x)\tOffline data collection activity \n\t\t\t\t\t", - (int)data->offline_data_collection_status); - pout("completed without error.\n"); - break; - case 0x03: - case 0x83: - pout("(0x%02x)\tReserved.\n", - (int)data->offline_data_collection_status); - break; - case 0x04: - case 0x84: - pout("(0x%02x)\tOffline data collection activity was \n\t\t\t\t\t", - (int)data->offline_data_collection_status); - pout("suspended by an interrupting command from host.\n"); - break; - case 0x05: - case 0x85: - pout("(0x%02x)\tOffline data collection activity was \n\t\t\t\t\t", - (int)data->offline_data_collection_status); - pout("aborted by an interrupting command from host.\n"); - break; - case 0x06: - case 0x86: - pout("(0x%02x)\tOffline data collection activity was \n\t\t\t\t\t", - (int)data->offline_data_collection_status); - pout("aborted by the device with a fatal error.\n"); - break; - default: - if ( ((data->offline_data_collection_status >= 0x07) && - (data->offline_data_collection_status <= 0x3f)) || - ((data->offline_data_collection_status >= 0xc0) && - (data->offline_data_collection_status <= 0xff)) ) - pout("(0x%02x)\tVendor Specific.\n",(int)data->offline_data_collection_status); - else - pout("(0x%02x)\tReserved.\n",(int)data->offline_data_collection_status); - } - - // report on Automatic Data Collection Status. Only IBM documents - // this bit. - if (data->offline_data_collection_status & 0x80) - pout("\t\t\t\t\tAuto Off-line Data Collection: Enabled.\n"); - else - pout("\t\t\t\t\tAuto Off-line Data Collection: Disabled.\n"); - - return; -} - - - -void PrintSmartSelfExecStatus(struct ata_smart_values *data) -{ - pout("Self-test execution status: "); - - switch (data->self_test_exec_status >> 4) - { - case 0: - pout("(%4d)\tThe previous self-test routine completed\n\t\t\t\t\t", - (int)data->self_test_exec_status); - pout("without error or no self-test has ever \n\t\t\t\t\tbeen run.\n"); - break; - case 1: - pout("(%4d)\tThe self-test routine was aborted by\n\t\t\t\t\t", - (int)data->self_test_exec_status); - pout("the host.\n"); - break; - case 2: - pout("(%4d)\tThe self-test routine was interrupted\n\t\t\t\t\t", - (int)data->self_test_exec_status); - pout("by the host with a hard or soft reset.\n"); - break; - case 3: - pout("(%4d)\tA fatal error or unknown test error\n\t\t\t\t\t", - (int)data->self_test_exec_status); - pout("occurred while the device was executing\n\t\t\t\t\t"); - pout("its self-test routine and the device \n\t\t\t\t\t"); - pout("was unable to complete the self-test \n\t\t\t\t\t"); - pout("routine.\n"); - break; - case 4: - pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", - (int)data->self_test_exec_status); - pout("a test element that failed and the test\n\t\t\t\t\t"); - pout("element that failed is not known.\n"); - break; - case 5: - pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", - (int)data->self_test_exec_status); - pout("the electrical element of the test\n\t\t\t\t\t"); - pout("failed.\n"); - break; - case 6: - pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", - (int)data->self_test_exec_status); - pout("the servo (and/or seek) element of the \n\t\t\t\t\t"); - pout("test failed.\n"); - break; - case 7: - pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", - (int)data->self_test_exec_status); - pout("the read element of the test failed.\n"); - break; - case 15: - pout("(%4d)\tSelf-test routine in progress...\n\t\t\t\t\t", - (int)data->self_test_exec_status); - pout("%1d0%% of test remaining.\n", - (int)(data->self_test_exec_status & 0x0f)); - break; - default: - pout("(%4d)\tReserved.\n", - (int)data->self_test_exec_status); - break; - } - -} - - - -void PrintSmartTotalTimeCompleteOffline ( struct ata_smart_values *data){ - pout("Total time to complete off-line \n"); - pout("data collection: \t\t (%4d) seconds.\n", - (int)data->total_time_to_complete_off_line); -} - - - -void PrintSmartOfflineCollectCap(struct ata_smart_values *data){ - pout("Offline data collection\n"); - pout("capabilities: \t\t\t (0x%02x) ", - (int)data->offline_data_collection_capability); - - if (data->offline_data_collection_capability == 0x00){ - pout("\tOff-line data collection not supported.\n"); - } - else { - pout( "%s\n", isSupportExecuteOfflineImmediate(data)? - "SMART execute Offline immediate." : - "No SMART execute Offline immediate."); - - pout( "\t\t\t\t\t%s\n", isSupportAutomaticTimer(data)? - "Automatic timer ON/OFF support.": - "No Automatic timer ON/OFF support."); - - pout( "\t\t\t\t\t%s\n", isSupportOfflineAbort(data)? - "Abort Offline collection upon new\n\t\t\t\t\tcommand.": - "Suspend Offline collection upon new\n\t\t\t\t\tcommand."); - - pout( "\t\t\t\t\t%s\n", isSupportOfflineSurfaceScan(data)? - "Offline surface scan supported.": - "No Offline surface scan supported."); - - pout( "\t\t\t\t\t%s\n", isSupportSelfTest(data)? - "Self-test supported.": - "No Self-test supported."); - - pout( "\t\t\t\t\t%s\n", isSupportConveyanceSelfTest(data)? - "Conveyance Self-test supported.": - "No Conveyance Self-test supported."); - - pout( "\t\t\t\t\t%s\n", isSupportSelectiveSelfTest(data)? - "Selective Self-test supported.": - "No Selective Self-test supported."); - } -} - - - -void PrintSmartCapability ( struct ata_smart_values *data) -{ - pout("SMART capabilities: "); - pout("(0x%04x)\t", (int)data->smart_capability); - - if (data->smart_capability == 0x00) - { - pout("Automatic saving of SMART data\t\t\t\t\tis not implemented.\n"); - } - else - { - - pout( "%s\n", (data->smart_capability & 0x01)? - "Saves SMART data before entering\n\t\t\t\t\tpower-saving mode.": - "Does not save SMART data before\n\t\t\t\t\tentering power-saving mode."); - - if ( data->smart_capability & 0x02 ) - { - pout("\t\t\t\t\tSupports SMART auto save timer.\n"); - } - } -} - - - -void PrintSmartErrorLogCapability ( struct ata_smart_values *data) -{ - - pout("Error logging capability: "); - - if ( isSmartErrorLogCapable(data) ) - { - pout(" (0x%02x)\tError logging supported.\n", - (int)data->errorlog_capability); - } - else { - pout(" (0x%02x)\tError logging NOT supported.\n", - (int)data->errorlog_capability); - } -} - - - -void PrintSmartShortSelfTestPollingTime(struct ata_smart_values *data){ - if (isSupportSelfTest(data)){ - pout("Short self-test routine \n"); - pout("recommended polling time: \t (%4d) minutes.\n", - (int)data->short_test_completion_time); - } - else { - pout("Short self-test routine \n"); - pout("recommended polling time: \t Not Supported.\n"); - } -} - -void PrintSmartExtendedSelfTestPollingTime(struct ata_smart_values *data){ - if (isSupportSelfTest(data)){ - pout("Extended self-test routine \n"); - pout("recommended polling time: \t (%4d) minutes.\n", - (int)data->extend_test_completion_time); - } - else { - pout("Extended self-test routine \n"); - pout("recommended polling time: \t Not Supported.\n"); - } -} - -void PrintSmartConveyanceSelfTestPollingTime(struct ata_smart_values *data){ - if (isSupportConveyanceSelfTest(data)){ - pout("Extended self-test routine \n"); - pout("recommended polling time: \t (%4d) minutes.\n", - (int)data->conveyance_test_completion_time); - } - else { - pout("Extended self-test routine \n"); - pout("recommended polling time: \t Not Supported.\n"); - } -} - - - - - -// 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 -void PrintSmartAttribWithThres (struct ata_smart_values *data, - struct ata_smart_thresholds *thresholds, - int onlyfailed){ - int i; - int needheader=1; - char rawstring[64]; - - // step through all vendor attributes - for (i=0; i<NUMBER_ATA_SMART_ATTRIBUTES; i++){ - char *status; - struct ata_smart_attribute *disk=data->vendor_attributes+i; - struct ata_smart_threshold_entry *thre=thresholds->thres_entries+i; - - // consider only valid attributes - if (disk->id && thre->id){ - char *type; - int failednow,failedever; - char attributename[64]; - - failednow = (disk->current <= thre->threshold); - failedever= (disk->worst <= thre->threshold); - - // These break out of the loop if we are only printing certain entries... - if (onlyfailed==1 && (!disk->status.flag.prefailure || !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 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=" -"; - - // Print name of attribute - ataPrintSmartAttribName(attributename,disk->id, con->attributedefs[disk->id]); - pout("%-28s",attributename); - - // printing line for each valid attribute - type=disk->status.flag.prefailure?"Pre-fail":"Old_age"; - pout("0x%04x %.3d %.3d %.3d %-9s%-12s", - (int)disk->status.all, (int)disk->current, (int)disk->worst, - (int)thre->threshold, type, status); - - // print raw value of attribute - ataPrintSmartAttribRawValue(rawstring, disk, con->attributedefs); - pout("%s\n", rawstring); - - // print a warning if there is inconsistency here! - if (disk->id != thre->id){ - char atdat[64],atthr[64]; - ataPrintSmartAttribName(atdat, disk->id, con->attributedefs[disk->id]); - ataPrintSmartAttribName(atthr, thre->id, con->attributedefs[thre->id]); - pout("%-28s<== Data Page | WARNING: PREVIOUS ATTRIBUTE HAS TWO\n",atdat); - pout("%-28s<== Threshold Page | INCONSISTENT IDENTITIES IN THE DATA\n",atthr); - } - } - } - if (!needheader) pout("\n"); -} - -void ataPrintGeneralSmartValues(struct ata_smart_values *data, struct hd_driveid *drive){ - pout("General SMART Values:\n"); - - PrintSmartOfflineStatus(data); - - if (isSupportSelfTest(data)){ - PrintSmartSelfExecStatus (data); - } - - PrintSmartTotalTimeCompleteOffline(data); - PrintSmartOfflineCollectCap(data); - PrintSmartCapability(data); - - PrintSmartErrorLogCapability(data); - - pout( "\t\t\t\t\t%s\n", isGeneralPurposeLoggingCapable(drive)? - "General Purpose Logging supported.": - "No General Purpose Logging support."); - - if (isSupportSelfTest(data)){ - PrintSmartShortSelfTestPollingTime (data); - PrintSmartExtendedSelfTestPollingTime (data); - } - if (isSupportConveyanceSelfTest(data)) - PrintSmartConveyanceSelfTestPollingTime (data); - - pout("\n"); -} - -// Returns nonzero if region of memory contains non-zero entries -int nonempty(unsigned char *testarea,int n){ - int i; - for (i=0;i<n;i++) - if (testarea[i]) - return 1; - return 0; -} - -int ataPrintLogDirectory(struct ata_smart_log_directory *data){ - int i; - char *name; - - pout("SMART Log Directory Logging Version %d%s\n", - data->logversion, data->logversion==1?" [multi-sector log support]":""); - for (i=0; i<=255; i++){ - int numsect; - - // Directory log length - numsect = i? data->entry[i-1].numsectors : 1; - - // If the log is not empty, what is it's name - if (numsect){ - switch (i) { - case 0: - name="Log Directory"; break; - case 1: - name="Summary SMART error log"; break; - case 2: - name="Comprehensive SMART error log"; break; - case 3: - name="Extended Comprehensive SMART error log"; break; - case 6: - name="SMART self-test log"; break; - case 7: - name="Extended self-test log"; break; - case 9: - name="Selective self-test log"; break; - case 0x20: - name="Streaming performance log"; break; - case 0x21: - name="Write stream error log"; break; - case 0x22: - name="Read stream error log"; break; - case 0x23: - name="Delayed sector log"; break; - default: - if (0xa0<=i && i<=0xbf) - name="Device vendor specific log"; - else if (0x80<=i && i<=0x9f) - name="Host vendor specific log"; - else - name="Reserved log"; - break; - } - - // print name and length of log - pout("Log at address 0x%02x has %03d sectors [%s]\n", - i, numsect, name); - } - } - return 0; -} - -// returns number of errors -int ataPrintSmartErrorlog (struct ata_smart_errorlog *data){ - int i,j,k; - - pout("SMART Error Log Version: %d\n", (int)data->revnumber); - - // if no errors logged, return - if (!data->error_log_pointer){ - pout("No Errors Logged\n\n"); - return 0; - } - QUIETON(con); - // If log pointer out of range, return - if (data->error_log_pointer>5){ - pout("Invalid Error Log index = 0x%02x (T13/1321D rev 1c " - "Section 8.41.6.8.2.2 gives valid range from 1 to 5)\n\n", - (int)data->error_log_pointer); - return 0; - } - - // Some internal consistency checking of the data structures - if ((data->ata_error_count-data->error_log_pointer)%5) { - pout("Warning: ATA error count %d inconsistent with error log pointer %d\n\n", - data->ata_error_count,data->error_log_pointer); - } - - // starting printing error log info - if (data->ata_error_count<=5) - pout( "ATA Error Count: %d\n", (int)data->ata_error_count); - else - pout( "ATA Error Count: %d (device log contains only the most recent five errors)\n", - (int)data->ata_error_count); - QUIETOFF(con); - pout("\tDCR = Device Control Register\n"); - pout("\tFR = Features Register\n"); - pout("\tSC = Sector Count Register\n"); - pout("\tSN = Sector Number Register\n"); - pout("\tCL = Cylinder Low Register\n"); - pout("\tCH = Cylinder High Register\n"); - pout("\tD/H = Device/Head Register\n"); - pout("\tCR = Content written to Command Register\n"); - pout("\tER = Error register\n"); - pout("\tSTA = Status register\n"); - pout("Timestamp is seconds since the previous disk power-on.\n"); - pout("Note: timestamp \"wraps\" after 2^32 msec = 49.710 days.\n\n"); - - // now step through the five error log data structures (table 39 of spec) - for (k = 4; k >= 0; k-- ) { - - // The error log data structure entries are a circular buffer - i=(data->error_log_pointer+k)%5; - - // Spec says: unused error log structures shall be zero filled - if (nonempty((unsigned char*)&(data->errorlog_struct[i]),sizeof(data->errorlog_struct[i]))){ - char *msgstate; - switch (data->errorlog_struct[i].error_struct.state){ - case 0x00: msgstate="in an unknown state";break; - case 0x01: msgstate="sleeping"; break; - case 0x02: msgstate="in standby mode"; break; - case 0x03: msgstate="active or idle"; break; - case 0x04: msgstate="doing SMART off-line or self test"; break; - default: msgstate="in a vendor specific or reserved state"; - } - // See table 42 of ATA5 spec - QUIETON(con); - pout("Error %d occurred at disk power-on lifetime: %d hours\n", - (int)(data->ata_error_count+k-4), (int)data->errorlog_struct[i].error_struct.timestamp); - QUIETOFF(con); - pout("When the command that caused the error occurred, the device was %s.\n",msgstate); - pout("After command completion occurred, registers were:\n"); - pout("ER:%02x SC:%02x SN:%02x CL:%02x CH:%02x D/H:%02x ST:%02x\n", - (int)data->errorlog_struct[i].error_struct.error_register, - (int)data->errorlog_struct[i].error_struct.sector_count, - (int)data->errorlog_struct[i].error_struct.sector_number, - (int)data->errorlog_struct[i].error_struct.cylinder_low, - (int)data->errorlog_struct[i].error_struct.cylinder_high, - (int)data->errorlog_struct[i].error_struct.drive_head, - (int)data->errorlog_struct[i].error_struct.status); - pout("Sequence of commands leading to the command that caused the error were:\n"); - pout("DCR FR SC SN CL CH D/H CR Timestamp\n"); - for ( j = 4; j >= 0; j--){ - struct ata_smart_errorlog_command_struct *thiscommand=&(data->errorlog_struct[i].commands[j]); - - // Spec says: unused data command structures shall be zero filled - if (nonempty((unsigned char*)thiscommand,sizeof(*thiscommand))) - pout(" %02x %02x %02x %02x %02x %02x %02x %02x %d.%03d\n", - (int)thiscommand->devicecontrolreg, - (int)thiscommand->featuresreg, - (int)thiscommand->sector_count, - (int)thiscommand->sector_number, - (int)thiscommand->cylinder_low, - (int)thiscommand->cylinder_high, - (int)thiscommand->drive_head, - (int)thiscommand->commandreg, - (unsigned int)(thiscommand->timestamp / 1000U), - (unsigned int)(thiscommand->timestamp % 1000U)); - } - pout("\n"); - } - } - QUIETON(con); - if (con->quietmode) - pout("\n"); - QUIETOFF(con); - return data->ata_error_count; -} - -// return value is number of entries found where the self-test showed an error -int ataPrintSmartSelfTestlog(struct ata_smart_selftestlog *data,int allentries){ - int i,j,noheaderprinted=1; - int retval=0; - - if (allentries) - pout("SMART Self-test log, version number %d\n",(int)data->revnumber); - if ((data->revnumber!=0x0001) && allentries && con->fixfirmwarebug != FIX_SAMSUNG) - pout("Warning - structure revision number does not match spec!\n"); - if (data->mostrecenttest==0){ - if (allentries) - pout("No self-tests have been logged\n\n"); - return 0; - } - - // print log - for (i=20;i>=0;i--){ - struct ata_smart_selftestlog_struct *log; - // log is a circular buffer - j=(i+data->mostrecenttest)%21; - log=data->selftest_struct+j; - - if (nonempty((unsigned char*)log,sizeof(*log))){ - char *msgtest,*msgstat,percent[64],firstlba[64]; - int errorfound=0; - - // test name - switch(log->selftestnumber){ - case 0: msgtest="Off-line "; break; - case 1: msgtest="Short off-line "; break; - case 2: msgtest="Extended off-line "; break; - case 127: msgtest="Abort off-line test"; break; - case 129: msgtest="Short captive "; break; - case 130: msgtest="Extended captive "; break; - default: msgtest="Unknown test "; - } - - // test status - switch((log->selfteststatus)>>4){ - case 0:msgstat="Completed "; break; - case 1:msgstat="Aborted by host "; break; - case 2:msgstat="Interrupted (host reset) "; break; - case 3:msgstat="Fatal or unknown error "; errorfound=1; break; - case 4:msgstat="Completed: unknown failure "; errorfound=1; break; - case 5:msgstat="Completed: electrical failure"; errorfound=1; break; - case 6:msgstat="Completed: servo/seek failure"; errorfound=1; break; - case 7:msgstat="Completed: read failure "; errorfound=1; break; - case 8:msgstat="Completed: handling damage?? "; errorfound=1; break; - case 15:msgstat="Test in progress "; break; - default:msgstat="Unknown/reserved test status "; - } - - retval+=errorfound; - sprintf(percent,"%1d0%%",(log->selfteststatus)&0xf); - - // T13/1321D revision 1c: (Data structure Rev #1) - - //The failing LBA shall be the LBA of the uncorrectable sector - //that caused the test to fail. If the device encountered more - //than one uncorrectable sector during the test, this field - //shall indicate the LBA of the first uncorrectable sector - //encountered. If the test passed or the test failed for some - //reason other than an uncorrectable sector, the value of this - //field is undefined. - - // This is true in ALL ATA-5 specs - - if (!errorfound || log->lbafirstfailure==0xffffffff || log->lbafirstfailure==0x00000000) - sprintf(firstlba,"%s","-"); - else - sprintf(firstlba,"0x%08x",log->lbafirstfailure); - - if (noheaderprinted && (allentries || errorfound)){ - pout("Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error\n"); - noheaderprinted=0; - } - - if (allentries || errorfound) - pout("#%2d %s %s %s %8d %s\n",21-i,msgtest,msgstat, - percent,(int)log->timestamp,firstlba); - } - } - if (!allentries && retval) - pout("\n"); - return retval; -} - -void ataPseudoCheckSmart ( struct ata_smart_values *data, - struct ata_smart_thresholds *thresholds) { - int i; - int failed = 0; - for (i = 0 ; i < NUMBER_ATA_SMART_ATTRIBUTES ; i++) { - if (data->vendor_attributes[i].id && - thresholds->thres_entries[i].id && - data->vendor_attributes[i].status.flag.prefailure && - (data->vendor_attributes[i].current <= thresholds->thres_entries[i].threshold) && - (thresholds->thres_entries[i].threshold != 0xFE)){ - pout("Attribute ID %d Failed\n",(int)data->vendor_attributes[i].id); - failed = 1; - } - } - pout("%s\n", ( failed )? - "SMART overall-health self-assessment test result: FAILED!\n" - "Drive failure expected in less than 24 hours. SAVE ALL DATA": - "SMART overall-health self-assessment test result: PASSED"); -} - - -// Compares failure type to policy in effect, and either exits or -// simply returns to the calling routine. -void failuretest(int type, int returnvalue){ - - // If this is an error in an "optional" SMART command - if (type==OPTIONAL_CMD){ - if (con->conservative){ - pout("An optional SMART command has failed: exiting. To continue, set the tolerance level to something other than 'conservative'\n"); - exit(returnvalue); - } - return; - } - - // If this is an error in a "mandatory" SMART command - if (type==MANDATORY_CMD){ - if (con->permissive) - return; - pout("A mandatory SMART command has failed: exiting. To continue, use the -T option to set the tolerance level to 'permissive'\n"); - exit(returnvalue); - } - - pout("Smartctl internal error in failuretest(type=%d). Please contact %s\n",type,PROJECTHOME); - exit(returnvalue|FAILCMD); -} - -// Used to warn users about invalid checksums. Action to be taken may be -// altered by the user. -void checksumwarning(const char *string){ - // user has asked us to ignore checksum errors - if (con->checksumignore) - return; - - pout("Warning! %s error: invalid SMART checksum.\n",string); - - // user has asked us to fail on checksum errors - if (con->checksumfail) - exit(FAILSMART); - - return; -} - -// Initialize to zero just in case some SMART routines don't work -struct hd_driveid drive; -struct ata_smart_values smartval; -struct ata_smart_thresholds smartthres; -struct ata_smart_errorlog smarterror; -struct ata_smart_selftestlog smartselftest; - -int ataPrintMain (int fd){ - int timewait,code; - int returnval=0; - - // Start by getting Drive ID information. We need this, to know if SMART is supported. - if (ataReadHDIdentity(fd,&drive)){ - pout("Smartctl: Hard Drive Read Identity Failed\n\n"); - failuretest(MANDATORY_CMD, returnval|=FAILID); - } - - // If requested, show which presets would be used for this drive and exit. - if (con->showpresets) { - showpresets(&drive); - exit(0); - } - - // Use preset vendor attribute options unless user has requested otherwise. - if (!con->ignorepresets) - applypresets(&drive, con->attributedefs, con); - - // Print most drive identity information if requested - if (con->driveinfo){ - pout("=== START OF INFORMATION SECTION ===\n"); - ataPrintDriveInfo(&drive); - } - - // now check if drive supports SMART; otherwise time to exit - if (!ataSmartSupport(&drive)){ - pout("SMART support is: Unavailable - device lacks SMART capability.\n"); - failuretest(MANDATORY_CMD, returnval|=FAILSMART); - pout(" Checking to be sure by trying SMART ENABLE command.\n"); - if (ataEnableSmart(fd)){ - pout(" No SMART functionality found. Sorry.\n"); - failuretest(MANDATORY_CMD,returnval|=FAILSMART); - } - else - pout(" SMART appears to work. Continuing.\n"); - if (!con->driveinfo) pout("\n"); - } - - // Now print remaining drive info: is SMART enabled? - if (con->driveinfo){ - pout("SMART support is: Available - device has SMART capability.\n"); - if (ataDoesSmartWork(fd)) - pout("SMART support is: Enabled\n"); - else - pout("SMART support is: Disabled\n"); - pout("\n"); - } - - - // START OF THE ENABLE/DISABLE SECTION OF THE CODE - if (con->smartenable || con->smartdisable || - con->smartautosaveenable || con->smartautosavedisable || - con->smartautoofflineenable || con->smartautoofflinedisable) - pout("=== START OF ENABLE/DISABLE COMMANDS SECTION ===\n"); - - // Enable/Disable SMART commands - if (con->smartenable){ - if (ataEnableSmart(fd)) { - pout("Smartctl: SMART Enable Failed.\n\n"); - failuretest(MANDATORY_CMD, returnval|=FAILSMART); - } - else - pout("SMART Enabled.\n"); - } - - // From here on, every command requires that SMART be enabled... - if (!ataDoesSmartWork(fd)) { - pout("SMART Disabled. Use option -s with argument 'on' to enable it.\n"); - return returnval; - } - - // Turn off SMART on device - if (con->smartdisable){ - if (ataDisableSmart(fd)) { - pout( "Smartctl: SMART Disable Failed.\n\n"); - failuretest(MANDATORY_CMD,returnval|=FAILSMART); - } - pout("SMART Disabled. Use option -s with argument 'on' to enable it.\n"); - return returnval; - } - - // Let's ALWAYS issue this command to get the SMART status - code=ataSmartStatus2(fd); - if (code==-1) - failuretest(MANDATORY_CMD, returnval|=FAILSMART); - - // Enable/Disable Auto-save attributes - if (con->smartautosaveenable){ - if (ataEnableAutoSave(fd)){ - pout( "Smartctl: SMART Enable Attribute Autosave Failed.\n\n"); - failuretest(MANDATORY_CMD, returnval|=FAILSMART); - } - else - pout("SMART Attribute Autosave Enabled.\n"); - } - if (con->smartautosavedisable){ - if (ataDisableAutoSave(fd)){ - pout( "Smartctl: SMART Disable Attribute Autosave Failed.\n\n"); - failuretest(MANDATORY_CMD, returnval|=FAILSMART); - } - else - pout("SMART Attribute Autosave Disabled.\n"); - } - - // for everything else read values and thresholds are needed - if (ataReadSmartValues(fd, &smartval)){ - pout("Smartctl: SMART Read Values failed.\n\n"); - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - } - if (ataReadSmartThresholds(fd, &smartthres)){ - pout("Smartctl: SMART Read Thresholds failed.\n\n"); - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - } - - // Enable/Disable Off-line testing - if (con->smartautoofflineenable){ - if (!isSupportAutomaticTimer(&smartval)){ - pout("Warning: device does not support SMART Automatic Timers.\n\n"); - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - } - if (ataEnableAutoOffline(fd)){ - pout( "Smartctl: SMART Enable Automatic Offline Failed.\n\n"); - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - } - else - pout("SMART Automatic Offline Testing Enabled every four hours.\n"); - } - if (con->smartautoofflinedisable){ - if (!isSupportAutomaticTimer(&smartval)){ - pout("Warning: device does not support SMART Automatic Timers.\n\n"); - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - } - if (ataDisableAutoOffline(fd)){ - pout("Smartctl: SMART Disable Automatic Offline Failed.\n\n"); - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - } - else - pout("SMART Automatic Offline Testing Disabled.\n"); - } - - // all this for a newline! - if (con->smartenable || con->smartdisable || - con->smartautosaveenable || con->smartautosavedisable || - con->smartautoofflineenable || con->smartautoofflinedisable) - pout("\n"); - - // START OF READ-ONLY OPTIONS APART FROM -V and -i - if (con->checksmart || con->generalsmartvalues || con->smartvendorattrib || con->smarterrorlog || con->smartselftestlog) - pout("=== START OF READ SMART DATA SECTION ===\n"); - - // Check SMART status (use previously returned value) - if (con->checksmart){ - switch (code) { - - 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 (con->smartvendorattrib) - pout("See vendor-specific Attribute list for marginal Attributes.\n\n"); - else { - QUIETON(con); - pout("Please note the following marginal Attributes:\n"); - PrintSmartAttribWithThres(&smartval, &smartthres,2); - } - returnval|=FAILAGE; - } - else - pout("\n"); - break; - - case 1: - // The case where the disk health is NOT OK - QUIETON(con); - pout("SMART overall-health self-assessment test result: FAILED!\n" - "Drive failure expected in less than 24 hours. SAVE ALL DATA.\n"); - QUIETOFF(con); - if (ataCheckSmart(&smartval, &smartthres,1)){ - returnval|=FAILATTR; - if (con->smartvendorattrib) - pout("See vendor-specific Attribute list for failed Attributes.\n\n"); - else { - QUIETON(con); - pout("Failed Attributes:\n"); - PrintSmartAttribWithThres(&smartval, &smartthres,1); - } - } - else - pout("No failed Attributes found.\n\n"); - returnval|=FAILSTATUS; - QUIETOFF(con); - break; - - case -1: - default: - // The case where something went wrong with HDIO_DRIVE_TASK ioctl() - if (ataCheckSmart(&smartval, &smartthres,1)){ - QUIETON(con); - pout("SMART overall-health self-assessment test result: FAILED!\n" - "Drive failure expected in less than 24 hours. SAVE ALL DATA.\n"); - QUIETOFF(con); - returnval|=FAILATTR; - returnval|=FAILSTATUS; - if (con->smartvendorattrib) - pout("See vendor-specific Attribute list for failed Attributes.\n\n"); - else { - QUIETON(con); - pout("Failed Attributes:\n"); - PrintSmartAttribWithThres(&smartval, &smartthres,1); - } - } - else { - pout("SMART overall-health self-assessment test result: PASSED\n"); - if (ataCheckSmart(&smartval, &smartthres,0)){ - if (con->smartvendorattrib) - pout("See vendor-specific Attribute list for marginal Attributes.\n\n"); - else { - QUIETON(con); - pout("Please note the following marginal Attributes:\n"); - PrintSmartAttribWithThres(&smartval, &smartthres,2); - } - returnval|=FAILAGE; - } - else - pout("\n"); - } - QUIETOFF(con); - break; - } // end of switch statement - - QUIETOFF(con); - } // end of checking SMART Status - - // Print general SMART values - if (con->generalsmartvalues) - ataPrintGeneralSmartValues(&smartval, &drive); - - // Print vendor-specific attributes - if (con->smartvendorattrib){ - QUIETON(con); - PrintSmartAttribWithThres(&smartval, &smartthres,con->quietmode?2:0); - QUIETOFF(con); - } - - // Print SMART log Directory. For the moment this command is hidden - if (con->smartlogdirectory){ - struct ata_smart_log_directory smartlogdirectory; - if (!isGeneralPurposeLoggingCapable(&drive)){ - pout("Warning: device does not support General Purpose Logging\n"); - } - else { - QUIETON(con); - pout("Log Directory Supported\n"); - if (ataReadLogDirectory(fd, &smartlogdirectory)){ - QUIETOFF(con); - pout("Read Log Directory failed.\n\n"); - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - } - else - ataPrintLogDirectory( &smartlogdirectory); - } - QUIETOFF(con); - } - - // Print SMART error log - if (con->smarterrorlog){ - if (!isSmartErrorLogCapable(&smartval)){ - pout("Warning: device does not support Error Logging\n"); - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - } - else { - if (ataReadErrorLog(fd, &smarterror)){ - pout("Smartctl: SMART Errorlog Read Failed\n"); - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - } - else { - // quiet mode is turned on inside ataPrintSmartErrorLog() - if (ataPrintSmartErrorlog(&smarterror)) - returnval|=FAILERR; - QUIETOFF(con); - } - } - } - - // Print SMART self-test log - if (con->smartselftestlog){ - // Note that in spite of its name, isSmartErrorLogCapable() is - // the CORRECT way to see if a device supports the self-test log. - // The ATA spec says "if this command (READ LOG) is implemented, - // all address values for which the contents are defined shall be - // implemented...". Since both the SMART self-test logs AND the - // SMART error logs are defined, if one will work then so will the - // other. - if (!isSmartErrorLogCapable(&smartval)){ - pout("Warning: device does not support Self Test Logging\n"); - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - } - else { - if(ataReadSelfTestLog(fd, &smartselftest)){ - pout("Smartctl: SMART Self Test Log Read Failed\n"); - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - } - else { - QUIETON(con); - if (ataPrintSmartSelfTestlog(&smartselftest,!con->quietmode)) - returnval|=FAILLOG; - QUIETOFF(con); - pout("\n"); - } - } - } - - // START OF THE TESTING SECTION OF THE CODE. IF NO TESTING, RETURN - if (con->testcase==-1) - return returnval; - - pout("=== START OF OFFLINE IMMEDIATE AND SELF-TEST SECTION ===\n"); - // if doing a self-test, be sure it's supported by the hardware - if (con->testcase==OFFLINE_FULL_SCAN && !isSupportExecuteOfflineImmediate(&smartval)){ - pout("Warning: device does not support Execute Off-Line Immediate function.\n\n"); - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - } - else if (!isSupportSelfTest(&smartval)){ - pout("Warning: device does not support Self-Test functions.\n\n"); - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - } - // Now do the test. Note ataSmartTest prints its own error/success - // messages - if (ataSmartTest(fd, con->testcase)) - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - - // Tell user how long test will take to complete. This is tricky - // because in the case of an Offline Full Scan, the completion timer - // is volatile, and needs to be read AFTER the command is given. If - // this will interrupt the Offline Full Scan, we don't do it, just - // warn user. - if (con->testcase==OFFLINE_FULL_SCAN){ - if (isSupportOfflineAbort(&smartval)) - pout("Note: giving further SMART commands will abort Offline testing\n"); - else if (ataReadSmartValues(fd, &smartval)){ - pout("Smartctl: SMART Read Values failed.\n"); - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - } - } - - // Now say how long the test will take to complete - if ((timewait=TestTime(&smartval,con->testcase))){ - pout("Please wait %d %s for test to complete.\n", - (int)timewait, con->testcase==OFFLINE_FULL_SCAN?"seconds":"minutes"); - - if (con->testcase!=SHORT_CAPTIVE_SELF_TEST && con->testcase!=EXTEND_CAPTIVE_SELF_TEST) - pout("Use smartctl -X to abort test.\n"); - } - return returnval; -} diff --git a/sm5/ataprint.cpp b/sm5/ataprint.cpp deleted file mode 100644 index 726110bb2..000000000 --- a/sm5/ataprint.cpp +++ /dev/null @@ -1,1225 +0,0 @@ -/* - * ataprint.c - * - * Home page of code is: http://smartmontools.sourceforge.net - * - * Copyright (C) 2002-3 Bruce Allen <smartmontools-support@lists.sourceforge.net> - * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org> - * - * 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 Software Foundation; either version 2, or (at your option) - * any later version. - * - * You should have received a copy of the GNU General Public License - * (for example COPYING); if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * This code was originally developed as a Senior Thesis by Michael Cornwell - * at the Concurrent Systems Laboratory (now part of the Storage Systems - * Research Center), Jack Baskin School of Engineering, University of - * California, Santa Cruz. http://ssrc.soe.ucsc.edu/ - * - */ - -#include <ctype.h> -#include <stdio.h> -#include <syslog.h> -#include <string.h> -#include "atacmds.h" -#include "ataprint.h" -#include "smartctl.h" -#include "extern.h" -#include "utility.h" -#include "knowndrives.h" - -const char *ataprint_c_cvsid="$Id: ataprint.cpp,v 1.85 2003/04/25 22:31:41 ballen4705 Exp $" -ATACMDS_H_CVSID ATAPRINT_H_CVSID EXTERN_H_CVSID KNOWNDRIVES_H_CVSID SMARTCTL_H_CVSID UTILITY_H_CVSID; - -// for passing global control variables -extern smartmonctrl *con; - -// Copies n bytes (or n-1 if n is odd) from in to out, but swaps adjacents -// bytes. -void swapbytes(char *out, const char *in, size_t n) -{ - size_t i; - - for (i = 0; i < n; i += 2) { - out[i] = in[i+1]; - out[i+1] = in[i]; - } -} - -// Copies in to out, but removes leading and trailing whitespace. -void trim(char *out, const char *in) -{ - int i, first, last; - - // Find the first non-space character (maybe none). - first = -1; - for (i = 0; in[i]; i++) - if (!isspace(in[i])) { - first = i; - break; - } - - if (first == -1) { - // There are no non-space characters. - out[0] = '\0'; - return; - } - - // Find the last non-space character. - for (i = strlen(in)-1; i >= first && isspace(in[i]); i--) - ; - last = i; - - strncpy(out, in+first, last-first+1); - out[last-first+1] = '\0'; -} - -// Convenience function for formatting strings from hd_driveid. -void formatdriveidstring(char *out, const char *in, int n) -{ - char tmp[65]; - - n = n > 64 ? 64 : n; - swapbytes(tmp, in, n); - tmp[n] = '\0'; - trim(out, tmp); -} - -// Function for printing ASCII byte-swapped strings, skipping white -// space. This is needed on little-endian architectures, eg Intel, -// Alpha. If someone wants to run this on SPARC they'll need to test -// for the Endian-ness and skip the byte swapping if it's big-endian. -void printswap(char *output, char *in, unsigned int n){ - formatdriveidstring(output, in, n); - if (*output) - pout("%s\n", output); - else - pout("[No Information Found]\n"); -} - -void ataPrintDriveInfo (struct hd_driveid *drive){ - int version, drivetype; - const char *description; - char unknown[64], timedatetz[64]; - unsigned short minorrev; - char model[64], serial[64], firm[64]; - - - // print out model, serial # and firmware versions (byte-swap ASCI strings) - pout("Device Model: "); - printswap(model, drive->model,40); - - pout("Serial Number: "); - printswap(serial, drive->serial_no,20); - - pout("Firmware Version: "); - printswap(firm, drive->fw_rev,8); - - // See if drive is recognized - drivetype=lookupdrive(model, firm); - pout("Device is: %s\n", drivetype<0? - "Not in smartctl database [for details use: -P showall]": - "In smartctl database [for details use: -P show]"); - - // now get ATA version info - version=ataVersionInfo(&description,drive, &minorrev); - - // unrecognized minor revision code - if (!description){ - if (!minorrev) - sprintf(unknown, "Exact ATA specification draft version not indicated"); - else - sprintf(unknown,"Not recognized. Minor revision code: 0x%02hx", minorrev); - description=unknown; - } - - - // SMART Support was first added into the ATA/ATAPI-3 Standard with - // Revision 3 of the document, July 25, 1995. Look at the "Document - // Status" revision commands at the beginning of - // http://www.t13.org/project/d2008r6.pdf to see this. So it's not - // enough to check if we are ATA-3. Version=-3 indicates ATA-3 - // BEFORE Revision 3. - pout("ATA Version is: %d\n",(int)abs(version)); - pout("ATA Standard is: %s\n",description); - - // print current time and date and timezone - dateandtimezone(timedatetz); - pout("Local Time is: %s\n", timedatetz); - - // Print warning message, if there is one - if (drivetype>=0 && knowndrives[drivetype].warningmsg) - pout("\n==> WARNING: %s\n\n", knowndrives[drivetype].warningmsg); - - if (version>=3) - return; - - pout("SMART is only available in ATA Version 3 Revision 3 or greater.\n"); - pout("We will try to proceed in spite of this.\n"); - return; -} - - -/* prints verbose value Off-line data collection status byte */ -void PrintSmartOfflineStatus(struct ata_smart_values *data){ - - pout("Off-line data collection status: "); - - switch(data->offline_data_collection_status){ - case 0x00: - case 0x80: - pout("(0x%02x)\tOffline data collection activity was\n\t\t\t\t\t", - (int)data->offline_data_collection_status); - pout("never started.\n"); - break; - case 0x01: - case 0x81: - pout("(0x%02x)\tReserved.\n", - (int)data->offline_data_collection_status); - break; - case 0x02: - case 0x82: - pout("(0x%02x)\tOffline data collection activity \n\t\t\t\t\t", - (int)data->offline_data_collection_status); - pout("completed without error.\n"); - break; - case 0x03: - case 0x83: - pout("(0x%02x)\tReserved.\n", - (int)data->offline_data_collection_status); - break; - case 0x04: - case 0x84: - pout("(0x%02x)\tOffline data collection activity was \n\t\t\t\t\t", - (int)data->offline_data_collection_status); - pout("suspended by an interrupting command from host.\n"); - break; - case 0x05: - case 0x85: - pout("(0x%02x)\tOffline data collection activity was \n\t\t\t\t\t", - (int)data->offline_data_collection_status); - pout("aborted by an interrupting command from host.\n"); - break; - case 0x06: - case 0x86: - pout("(0x%02x)\tOffline data collection activity was \n\t\t\t\t\t", - (int)data->offline_data_collection_status); - pout("aborted by the device with a fatal error.\n"); - break; - default: - if ( ((data->offline_data_collection_status >= 0x07) && - (data->offline_data_collection_status <= 0x3f)) || - ((data->offline_data_collection_status >= 0xc0) && - (data->offline_data_collection_status <= 0xff)) ) - pout("(0x%02x)\tVendor Specific.\n",(int)data->offline_data_collection_status); - else - pout("(0x%02x)\tReserved.\n",(int)data->offline_data_collection_status); - } - - // report on Automatic Data Collection Status. Only IBM documents - // this bit. - if (data->offline_data_collection_status & 0x80) - pout("\t\t\t\t\tAuto Off-line Data Collection: Enabled.\n"); - else - pout("\t\t\t\t\tAuto Off-line Data Collection: Disabled.\n"); - - return; -} - - - -void PrintSmartSelfExecStatus(struct ata_smart_values *data) -{ - pout("Self-test execution status: "); - - switch (data->self_test_exec_status >> 4) - { - case 0: - pout("(%4d)\tThe previous self-test routine completed\n\t\t\t\t\t", - (int)data->self_test_exec_status); - pout("without error or no self-test has ever \n\t\t\t\t\tbeen run.\n"); - break; - case 1: - pout("(%4d)\tThe self-test routine was aborted by\n\t\t\t\t\t", - (int)data->self_test_exec_status); - pout("the host.\n"); - break; - case 2: - pout("(%4d)\tThe self-test routine was interrupted\n\t\t\t\t\t", - (int)data->self_test_exec_status); - pout("by the host with a hard or soft reset.\n"); - break; - case 3: - pout("(%4d)\tA fatal error or unknown test error\n\t\t\t\t\t", - (int)data->self_test_exec_status); - pout("occurred while the device was executing\n\t\t\t\t\t"); - pout("its self-test routine and the device \n\t\t\t\t\t"); - pout("was unable to complete the self-test \n\t\t\t\t\t"); - pout("routine.\n"); - break; - case 4: - pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", - (int)data->self_test_exec_status); - pout("a test element that failed and the test\n\t\t\t\t\t"); - pout("element that failed is not known.\n"); - break; - case 5: - pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", - (int)data->self_test_exec_status); - pout("the electrical element of the test\n\t\t\t\t\t"); - pout("failed.\n"); - break; - case 6: - pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", - (int)data->self_test_exec_status); - pout("the servo (and/or seek) element of the \n\t\t\t\t\t"); - pout("test failed.\n"); - break; - case 7: - pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", - (int)data->self_test_exec_status); - pout("the read element of the test failed.\n"); - break; - case 15: - pout("(%4d)\tSelf-test routine in progress...\n\t\t\t\t\t", - (int)data->self_test_exec_status); - pout("%1d0%% of test remaining.\n", - (int)(data->self_test_exec_status & 0x0f)); - break; - default: - pout("(%4d)\tReserved.\n", - (int)data->self_test_exec_status); - break; - } - -} - - - -void PrintSmartTotalTimeCompleteOffline ( struct ata_smart_values *data){ - pout("Total time to complete off-line \n"); - pout("data collection: \t\t (%4d) seconds.\n", - (int)data->total_time_to_complete_off_line); -} - - - -void PrintSmartOfflineCollectCap(struct ata_smart_values *data){ - pout("Offline data collection\n"); - pout("capabilities: \t\t\t (0x%02x) ", - (int)data->offline_data_collection_capability); - - if (data->offline_data_collection_capability == 0x00){ - pout("\tOff-line data collection not supported.\n"); - } - else { - pout( "%s\n", isSupportExecuteOfflineImmediate(data)? - "SMART execute Offline immediate." : - "No SMART execute Offline immediate."); - - pout( "\t\t\t\t\t%s\n", isSupportAutomaticTimer(data)? - "Automatic timer ON/OFF support.": - "No Automatic timer ON/OFF support."); - - pout( "\t\t\t\t\t%s\n", isSupportOfflineAbort(data)? - "Abort Offline collection upon new\n\t\t\t\t\tcommand.": - "Suspend Offline collection upon new\n\t\t\t\t\tcommand."); - - pout( "\t\t\t\t\t%s\n", isSupportOfflineSurfaceScan(data)? - "Offline surface scan supported.": - "No Offline surface scan supported."); - - pout( "\t\t\t\t\t%s\n", isSupportSelfTest(data)? - "Self-test supported.": - "No Self-test supported."); - - pout( "\t\t\t\t\t%s\n", isSupportConveyanceSelfTest(data)? - "Conveyance Self-test supported.": - "No Conveyance Self-test supported."); - - pout( "\t\t\t\t\t%s\n", isSupportSelectiveSelfTest(data)? - "Selective Self-test supported.": - "No Selective Self-test supported."); - } -} - - - -void PrintSmartCapability ( struct ata_smart_values *data) -{ - pout("SMART capabilities: "); - pout("(0x%04x)\t", (int)data->smart_capability); - - if (data->smart_capability == 0x00) - { - pout("Automatic saving of SMART data\t\t\t\t\tis not implemented.\n"); - } - else - { - - pout( "%s\n", (data->smart_capability & 0x01)? - "Saves SMART data before entering\n\t\t\t\t\tpower-saving mode.": - "Does not save SMART data before\n\t\t\t\t\tentering power-saving mode."); - - if ( data->smart_capability & 0x02 ) - { - pout("\t\t\t\t\tSupports SMART auto save timer.\n"); - } - } -} - - - -void PrintSmartErrorLogCapability ( struct ata_smart_values *data) -{ - - pout("Error logging capability: "); - - if ( isSmartErrorLogCapable(data) ) - { - pout(" (0x%02x)\tError logging supported.\n", - (int)data->errorlog_capability); - } - else { - pout(" (0x%02x)\tError logging NOT supported.\n", - (int)data->errorlog_capability); - } -} - - - -void PrintSmartShortSelfTestPollingTime(struct ata_smart_values *data){ - if (isSupportSelfTest(data)){ - pout("Short self-test routine \n"); - pout("recommended polling time: \t (%4d) minutes.\n", - (int)data->short_test_completion_time); - } - else { - pout("Short self-test routine \n"); - pout("recommended polling time: \t Not Supported.\n"); - } -} - -void PrintSmartExtendedSelfTestPollingTime(struct ata_smart_values *data){ - if (isSupportSelfTest(data)){ - pout("Extended self-test routine \n"); - pout("recommended polling time: \t (%4d) minutes.\n", - (int)data->extend_test_completion_time); - } - else { - pout("Extended self-test routine \n"); - pout("recommended polling time: \t Not Supported.\n"); - } -} - -void PrintSmartConveyanceSelfTestPollingTime(struct ata_smart_values *data){ - if (isSupportConveyanceSelfTest(data)){ - pout("Extended self-test routine \n"); - pout("recommended polling time: \t (%4d) minutes.\n", - (int)data->conveyance_test_completion_time); - } - else { - pout("Extended self-test routine \n"); - pout("recommended polling time: \t Not Supported.\n"); - } -} - - - - - -// 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 -void PrintSmartAttribWithThres (struct ata_smart_values *data, - struct ata_smart_thresholds *thresholds, - int onlyfailed){ - int i; - int needheader=1; - char rawstring[64]; - - // step through all vendor attributes - for (i=0; i<NUMBER_ATA_SMART_ATTRIBUTES; i++){ - char *status; - struct ata_smart_attribute *disk=data->vendor_attributes+i; - struct ata_smart_threshold_entry *thre=thresholds->thres_entries+i; - - // consider only valid attributes - if (disk->id && thre->id){ - char *type; - int failednow,failedever; - char attributename[64]; - - failednow = (disk->current <= thre->threshold); - failedever= (disk->worst <= thre->threshold); - - // These break out of the loop if we are only printing certain entries... - if (onlyfailed==1 && (!disk->status.flag.prefailure || !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 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=" -"; - - // Print name of attribute - ataPrintSmartAttribName(attributename,disk->id, con->attributedefs[disk->id]); - pout("%-28s",attributename); - - // printing line for each valid attribute - type=disk->status.flag.prefailure?"Pre-fail":"Old_age"; - pout("0x%04x %.3d %.3d %.3d %-9s%-12s", - (int)disk->status.all, (int)disk->current, (int)disk->worst, - (int)thre->threshold, type, status); - - // print raw value of attribute - ataPrintSmartAttribRawValue(rawstring, disk, con->attributedefs); - pout("%s\n", rawstring); - - // print a warning if there is inconsistency here! - if (disk->id != thre->id){ - char atdat[64],atthr[64]; - ataPrintSmartAttribName(atdat, disk->id, con->attributedefs[disk->id]); - ataPrintSmartAttribName(atthr, thre->id, con->attributedefs[thre->id]); - pout("%-28s<== Data Page | WARNING: PREVIOUS ATTRIBUTE HAS TWO\n",atdat); - pout("%-28s<== Threshold Page | INCONSISTENT IDENTITIES IN THE DATA\n",atthr); - } - } - } - if (!needheader) pout("\n"); -} - -void ataPrintGeneralSmartValues(struct ata_smart_values *data, struct hd_driveid *drive){ - pout("General SMART Values:\n"); - - PrintSmartOfflineStatus(data); - - if (isSupportSelfTest(data)){ - PrintSmartSelfExecStatus (data); - } - - PrintSmartTotalTimeCompleteOffline(data); - PrintSmartOfflineCollectCap(data); - PrintSmartCapability(data); - - PrintSmartErrorLogCapability(data); - - pout( "\t\t\t\t\t%s\n", isGeneralPurposeLoggingCapable(drive)? - "General Purpose Logging supported.": - "No General Purpose Logging support."); - - if (isSupportSelfTest(data)){ - PrintSmartShortSelfTestPollingTime (data); - PrintSmartExtendedSelfTestPollingTime (data); - } - if (isSupportConveyanceSelfTest(data)) - PrintSmartConveyanceSelfTestPollingTime (data); - - pout("\n"); -} - -// Returns nonzero if region of memory contains non-zero entries -int nonempty(unsigned char *testarea,int n){ - int i; - for (i=0;i<n;i++) - if (testarea[i]) - return 1; - return 0; -} - -int ataPrintLogDirectory(struct ata_smart_log_directory *data){ - int i; - char *name; - - pout("SMART Log Directory Logging Version %d%s\n", - data->logversion, data->logversion==1?" [multi-sector log support]":""); - for (i=0; i<=255; i++){ - int numsect; - - // Directory log length - numsect = i? data->entry[i-1].numsectors : 1; - - // If the log is not empty, what is it's name - if (numsect){ - switch (i) { - case 0: - name="Log Directory"; break; - case 1: - name="Summary SMART error log"; break; - case 2: - name="Comprehensive SMART error log"; break; - case 3: - name="Extended Comprehensive SMART error log"; break; - case 6: - name="SMART self-test log"; break; - case 7: - name="Extended self-test log"; break; - case 9: - name="Selective self-test log"; break; - case 0x20: - name="Streaming performance log"; break; - case 0x21: - name="Write stream error log"; break; - case 0x22: - name="Read stream error log"; break; - case 0x23: - name="Delayed sector log"; break; - default: - if (0xa0<=i && i<=0xbf) - name="Device vendor specific log"; - else if (0x80<=i && i<=0x9f) - name="Host vendor specific log"; - else - name="Reserved log"; - break; - } - - // print name and length of log - pout("Log at address 0x%02x has %03d sectors [%s]\n", - i, numsect, name); - } - } - return 0; -} - -// returns number of errors -int ataPrintSmartErrorlog (struct ata_smart_errorlog *data){ - int i,j,k; - - pout("SMART Error Log Version: %d\n", (int)data->revnumber); - - // if no errors logged, return - if (!data->error_log_pointer){ - pout("No Errors Logged\n\n"); - return 0; - } - QUIETON(con); - // If log pointer out of range, return - if (data->error_log_pointer>5){ - pout("Invalid Error Log index = 0x%02x (T13/1321D rev 1c " - "Section 8.41.6.8.2.2 gives valid range from 1 to 5)\n\n", - (int)data->error_log_pointer); - return 0; - } - - // Some internal consistency checking of the data structures - if ((data->ata_error_count-data->error_log_pointer)%5) { - pout("Warning: ATA error count %d inconsistent with error log pointer %d\n\n", - data->ata_error_count,data->error_log_pointer); - } - - // starting printing error log info - if (data->ata_error_count<=5) - pout( "ATA Error Count: %d\n", (int)data->ata_error_count); - else - pout( "ATA Error Count: %d (device log contains only the most recent five errors)\n", - (int)data->ata_error_count); - QUIETOFF(con); - pout("\tDCR = Device Control Register\n"); - pout("\tFR = Features Register\n"); - pout("\tSC = Sector Count Register\n"); - pout("\tSN = Sector Number Register\n"); - pout("\tCL = Cylinder Low Register\n"); - pout("\tCH = Cylinder High Register\n"); - pout("\tD/H = Device/Head Register\n"); - pout("\tCR = Content written to Command Register\n"); - pout("\tER = Error register\n"); - pout("\tSTA = Status register\n"); - pout("Timestamp is seconds since the previous disk power-on.\n"); - pout("Note: timestamp \"wraps\" after 2^32 msec = 49.710 days.\n\n"); - - // now step through the five error log data structures (table 39 of spec) - for (k = 4; k >= 0; k-- ) { - - // The error log data structure entries are a circular buffer - i=(data->error_log_pointer+k)%5; - - // Spec says: unused error log structures shall be zero filled - if (nonempty((unsigned char*)&(data->errorlog_struct[i]),sizeof(data->errorlog_struct[i]))){ - char *msgstate; - switch (data->errorlog_struct[i].error_struct.state){ - case 0x00: msgstate="in an unknown state";break; - case 0x01: msgstate="sleeping"; break; - case 0x02: msgstate="in standby mode"; break; - case 0x03: msgstate="active or idle"; break; - case 0x04: msgstate="doing SMART off-line or self test"; break; - default: msgstate="in a vendor specific or reserved state"; - } - // See table 42 of ATA5 spec - QUIETON(con); - pout("Error %d occurred at disk power-on lifetime: %d hours\n", - (int)(data->ata_error_count+k-4), (int)data->errorlog_struct[i].error_struct.timestamp); - QUIETOFF(con); - pout("When the command that caused the error occurred, the device was %s.\n",msgstate); - pout("After command completion occurred, registers were:\n"); - pout("ER:%02x SC:%02x SN:%02x CL:%02x CH:%02x D/H:%02x ST:%02x\n", - (int)data->errorlog_struct[i].error_struct.error_register, - (int)data->errorlog_struct[i].error_struct.sector_count, - (int)data->errorlog_struct[i].error_struct.sector_number, - (int)data->errorlog_struct[i].error_struct.cylinder_low, - (int)data->errorlog_struct[i].error_struct.cylinder_high, - (int)data->errorlog_struct[i].error_struct.drive_head, - (int)data->errorlog_struct[i].error_struct.status); - pout("Sequence of commands leading to the command that caused the error were:\n"); - pout("DCR FR SC SN CL CH D/H CR Timestamp\n"); - for ( j = 4; j >= 0; j--){ - struct ata_smart_errorlog_command_struct *thiscommand=&(data->errorlog_struct[i].commands[j]); - - // Spec says: unused data command structures shall be zero filled - if (nonempty((unsigned char*)thiscommand,sizeof(*thiscommand))) - pout(" %02x %02x %02x %02x %02x %02x %02x %02x %d.%03d\n", - (int)thiscommand->devicecontrolreg, - (int)thiscommand->featuresreg, - (int)thiscommand->sector_count, - (int)thiscommand->sector_number, - (int)thiscommand->cylinder_low, - (int)thiscommand->cylinder_high, - (int)thiscommand->drive_head, - (int)thiscommand->commandreg, - (unsigned int)(thiscommand->timestamp / 1000U), - (unsigned int)(thiscommand->timestamp % 1000U)); - } - pout("\n"); - } - } - QUIETON(con); - if (con->quietmode) - pout("\n"); - QUIETOFF(con); - return data->ata_error_count; -} - -// return value is number of entries found where the self-test showed an error -int ataPrintSmartSelfTestlog(struct ata_smart_selftestlog *data,int allentries){ - int i,j,noheaderprinted=1; - int retval=0; - - if (allentries) - pout("SMART Self-test log, version number %d\n",(int)data->revnumber); - if ((data->revnumber!=0x0001) && allentries && con->fixfirmwarebug != FIX_SAMSUNG) - pout("Warning - structure revision number does not match spec!\n"); - if (data->mostrecenttest==0){ - if (allentries) - pout("No self-tests have been logged\n\n"); - return 0; - } - - // print log - for (i=20;i>=0;i--){ - struct ata_smart_selftestlog_struct *log; - // log is a circular buffer - j=(i+data->mostrecenttest)%21; - log=data->selftest_struct+j; - - if (nonempty((unsigned char*)log,sizeof(*log))){ - char *msgtest,*msgstat,percent[64],firstlba[64]; - int errorfound=0; - - // test name - switch(log->selftestnumber){ - case 0: msgtest="Off-line "; break; - case 1: msgtest="Short off-line "; break; - case 2: msgtest="Extended off-line "; break; - case 127: msgtest="Abort off-line test"; break; - case 129: msgtest="Short captive "; break; - case 130: msgtest="Extended captive "; break; - default: msgtest="Unknown test "; - } - - // test status - switch((log->selfteststatus)>>4){ - case 0:msgstat="Completed "; break; - case 1:msgstat="Aborted by host "; break; - case 2:msgstat="Interrupted (host reset) "; break; - case 3:msgstat="Fatal or unknown error "; errorfound=1; break; - case 4:msgstat="Completed: unknown failure "; errorfound=1; break; - case 5:msgstat="Completed: electrical failure"; errorfound=1; break; - case 6:msgstat="Completed: servo/seek failure"; errorfound=1; break; - case 7:msgstat="Completed: read failure "; errorfound=1; break; - case 8:msgstat="Completed: handling damage?? "; errorfound=1; break; - case 15:msgstat="Test in progress "; break; - default:msgstat="Unknown/reserved test status "; - } - - retval+=errorfound; - sprintf(percent,"%1d0%%",(log->selfteststatus)&0xf); - - // T13/1321D revision 1c: (Data structure Rev #1) - - //The failing LBA shall be the LBA of the uncorrectable sector - //that caused the test to fail. If the device encountered more - //than one uncorrectable sector during the test, this field - //shall indicate the LBA of the first uncorrectable sector - //encountered. If the test passed or the test failed for some - //reason other than an uncorrectable sector, the value of this - //field is undefined. - - // This is true in ALL ATA-5 specs - - if (!errorfound || log->lbafirstfailure==0xffffffff || log->lbafirstfailure==0x00000000) - sprintf(firstlba,"%s","-"); - else - sprintf(firstlba,"0x%08x",log->lbafirstfailure); - - if (noheaderprinted && (allentries || errorfound)){ - pout("Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error\n"); - noheaderprinted=0; - } - - if (allentries || errorfound) - pout("#%2d %s %s %s %8d %s\n",21-i,msgtest,msgstat, - percent,(int)log->timestamp,firstlba); - } - } - if (!allentries && retval) - pout("\n"); - return retval; -} - -void ataPseudoCheckSmart ( struct ata_smart_values *data, - struct ata_smart_thresholds *thresholds) { - int i; - int failed = 0; - for (i = 0 ; i < NUMBER_ATA_SMART_ATTRIBUTES ; i++) { - if (data->vendor_attributes[i].id && - thresholds->thres_entries[i].id && - data->vendor_attributes[i].status.flag.prefailure && - (data->vendor_attributes[i].current <= thresholds->thres_entries[i].threshold) && - (thresholds->thres_entries[i].threshold != 0xFE)){ - pout("Attribute ID %d Failed\n",(int)data->vendor_attributes[i].id); - failed = 1; - } - } - pout("%s\n", ( failed )? - "SMART overall-health self-assessment test result: FAILED!\n" - "Drive failure expected in less than 24 hours. SAVE ALL DATA": - "SMART overall-health self-assessment test result: PASSED"); -} - - -// Compares failure type to policy in effect, and either exits or -// simply returns to the calling routine. -void failuretest(int type, int returnvalue){ - - // If this is an error in an "optional" SMART command - if (type==OPTIONAL_CMD){ - if (con->conservative){ - pout("An optional SMART command has failed: exiting. To continue, set the tolerance level to something other than 'conservative'\n"); - exit(returnvalue); - } - return; - } - - // If this is an error in a "mandatory" SMART command - if (type==MANDATORY_CMD){ - if (con->permissive) - return; - pout("A mandatory SMART command has failed: exiting. To continue, use the -T option to set the tolerance level to 'permissive'\n"); - exit(returnvalue); - } - - pout("Smartctl internal error in failuretest(type=%d). Please contact %s\n",type,PROJECTHOME); - exit(returnvalue|FAILCMD); -} - -// Used to warn users about invalid checksums. Action to be taken may be -// altered by the user. -void checksumwarning(const char *string){ - // user has asked us to ignore checksum errors - if (con->checksumignore) - return; - - pout("Warning! %s error: invalid SMART checksum.\n",string); - - // user has asked us to fail on checksum errors - if (con->checksumfail) - exit(FAILSMART); - - return; -} - -// Initialize to zero just in case some SMART routines don't work -struct hd_driveid drive; -struct ata_smart_values smartval; -struct ata_smart_thresholds smartthres; -struct ata_smart_errorlog smarterror; -struct ata_smart_selftestlog smartselftest; - -int ataPrintMain (int fd){ - int timewait,code; - int returnval=0; - - // Start by getting Drive ID information. We need this, to know if SMART is supported. - if (ataReadHDIdentity(fd,&drive)){ - pout("Smartctl: Hard Drive Read Identity Failed\n\n"); - failuretest(MANDATORY_CMD, returnval|=FAILID); - } - - // If requested, show which presets would be used for this drive and exit. - if (con->showpresets) { - showpresets(&drive); - exit(0); - } - - // Use preset vendor attribute options unless user has requested otherwise. - if (!con->ignorepresets) - applypresets(&drive, con->attributedefs, con); - - // Print most drive identity information if requested - if (con->driveinfo){ - pout("=== START OF INFORMATION SECTION ===\n"); - ataPrintDriveInfo(&drive); - } - - // now check if drive supports SMART; otherwise time to exit - if (!ataSmartSupport(&drive)){ - pout("SMART support is: Unavailable - device lacks SMART capability.\n"); - failuretest(MANDATORY_CMD, returnval|=FAILSMART); - pout(" Checking to be sure by trying SMART ENABLE command.\n"); - if (ataEnableSmart(fd)){ - pout(" No SMART functionality found. Sorry.\n"); - failuretest(MANDATORY_CMD,returnval|=FAILSMART); - } - else - pout(" SMART appears to work. Continuing.\n"); - if (!con->driveinfo) pout("\n"); - } - - // Now print remaining drive info: is SMART enabled? - if (con->driveinfo){ - pout("SMART support is: Available - device has SMART capability.\n"); - if (ataDoesSmartWork(fd)) - pout("SMART support is: Enabled\n"); - else - pout("SMART support is: Disabled\n"); - pout("\n"); - } - - - // START OF THE ENABLE/DISABLE SECTION OF THE CODE - if (con->smartenable || con->smartdisable || - con->smartautosaveenable || con->smartautosavedisable || - con->smartautoofflineenable || con->smartautoofflinedisable) - pout("=== START OF ENABLE/DISABLE COMMANDS SECTION ===\n"); - - // Enable/Disable SMART commands - if (con->smartenable){ - if (ataEnableSmart(fd)) { - pout("Smartctl: SMART Enable Failed.\n\n"); - failuretest(MANDATORY_CMD, returnval|=FAILSMART); - } - else - pout("SMART Enabled.\n"); - } - - // From here on, every command requires that SMART be enabled... - if (!ataDoesSmartWork(fd)) { - pout("SMART Disabled. Use option -s with argument 'on' to enable it.\n"); - return returnval; - } - - // Turn off SMART on device - if (con->smartdisable){ - if (ataDisableSmart(fd)) { - pout( "Smartctl: SMART Disable Failed.\n\n"); - failuretest(MANDATORY_CMD,returnval|=FAILSMART); - } - pout("SMART Disabled. Use option -s with argument 'on' to enable it.\n"); - return returnval; - } - - // Let's ALWAYS issue this command to get the SMART status - code=ataSmartStatus2(fd); - if (code==-1) - failuretest(MANDATORY_CMD, returnval|=FAILSMART); - - // Enable/Disable Auto-save attributes - if (con->smartautosaveenable){ - if (ataEnableAutoSave(fd)){ - pout( "Smartctl: SMART Enable Attribute Autosave Failed.\n\n"); - failuretest(MANDATORY_CMD, returnval|=FAILSMART); - } - else - pout("SMART Attribute Autosave Enabled.\n"); - } - if (con->smartautosavedisable){ - if (ataDisableAutoSave(fd)){ - pout( "Smartctl: SMART Disable Attribute Autosave Failed.\n\n"); - failuretest(MANDATORY_CMD, returnval|=FAILSMART); - } - else - pout("SMART Attribute Autosave Disabled.\n"); - } - - // for everything else read values and thresholds are needed - if (ataReadSmartValues(fd, &smartval)){ - pout("Smartctl: SMART Read Values failed.\n\n"); - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - } - if (ataReadSmartThresholds(fd, &smartthres)){ - pout("Smartctl: SMART Read Thresholds failed.\n\n"); - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - } - - // Enable/Disable Off-line testing - if (con->smartautoofflineenable){ - if (!isSupportAutomaticTimer(&smartval)){ - pout("Warning: device does not support SMART Automatic Timers.\n\n"); - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - } - if (ataEnableAutoOffline(fd)){ - pout( "Smartctl: SMART Enable Automatic Offline Failed.\n\n"); - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - } - else - pout("SMART Automatic Offline Testing Enabled every four hours.\n"); - } - if (con->smartautoofflinedisable){ - if (!isSupportAutomaticTimer(&smartval)){ - pout("Warning: device does not support SMART Automatic Timers.\n\n"); - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - } - if (ataDisableAutoOffline(fd)){ - pout("Smartctl: SMART Disable Automatic Offline Failed.\n\n"); - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - } - else - pout("SMART Automatic Offline Testing Disabled.\n"); - } - - // all this for a newline! - if (con->smartenable || con->smartdisable || - con->smartautosaveenable || con->smartautosavedisable || - con->smartautoofflineenable || con->smartautoofflinedisable) - pout("\n"); - - // START OF READ-ONLY OPTIONS APART FROM -V and -i - if (con->checksmart || con->generalsmartvalues || con->smartvendorattrib || con->smarterrorlog || con->smartselftestlog) - pout("=== START OF READ SMART DATA SECTION ===\n"); - - // Check SMART status (use previously returned value) - if (con->checksmart){ - switch (code) { - - 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 (con->smartvendorattrib) - pout("See vendor-specific Attribute list for marginal Attributes.\n\n"); - else { - QUIETON(con); - pout("Please note the following marginal Attributes:\n"); - PrintSmartAttribWithThres(&smartval, &smartthres,2); - } - returnval|=FAILAGE; - } - else - pout("\n"); - break; - - case 1: - // The case where the disk health is NOT OK - QUIETON(con); - pout("SMART overall-health self-assessment test result: FAILED!\n" - "Drive failure expected in less than 24 hours. SAVE ALL DATA.\n"); - QUIETOFF(con); - if (ataCheckSmart(&smartval, &smartthres,1)){ - returnval|=FAILATTR; - if (con->smartvendorattrib) - pout("See vendor-specific Attribute list for failed Attributes.\n\n"); - else { - QUIETON(con); - pout("Failed Attributes:\n"); - PrintSmartAttribWithThres(&smartval, &smartthres,1); - } - } - else - pout("No failed Attributes found.\n\n"); - returnval|=FAILSTATUS; - QUIETOFF(con); - break; - - case -1: - default: - // The case where something went wrong with HDIO_DRIVE_TASK ioctl() - if (ataCheckSmart(&smartval, &smartthres,1)){ - QUIETON(con); - pout("SMART overall-health self-assessment test result: FAILED!\n" - "Drive failure expected in less than 24 hours. SAVE ALL DATA.\n"); - QUIETOFF(con); - returnval|=FAILATTR; - returnval|=FAILSTATUS; - if (con->smartvendorattrib) - pout("See vendor-specific Attribute list for failed Attributes.\n\n"); - else { - QUIETON(con); - pout("Failed Attributes:\n"); - PrintSmartAttribWithThres(&smartval, &smartthres,1); - } - } - else { - pout("SMART overall-health self-assessment test result: PASSED\n"); - if (ataCheckSmart(&smartval, &smartthres,0)){ - if (con->smartvendorattrib) - pout("See vendor-specific Attribute list for marginal Attributes.\n\n"); - else { - QUIETON(con); - pout("Please note the following marginal Attributes:\n"); - PrintSmartAttribWithThres(&smartval, &smartthres,2); - } - returnval|=FAILAGE; - } - else - pout("\n"); - } - QUIETOFF(con); - break; - } // end of switch statement - - QUIETOFF(con); - } // end of checking SMART Status - - // Print general SMART values - if (con->generalsmartvalues) - ataPrintGeneralSmartValues(&smartval, &drive); - - // Print vendor-specific attributes - if (con->smartvendorattrib){ - QUIETON(con); - PrintSmartAttribWithThres(&smartval, &smartthres,con->quietmode?2:0); - QUIETOFF(con); - } - - // Print SMART log Directory. For the moment this command is hidden - if (con->smartlogdirectory){ - struct ata_smart_log_directory smartlogdirectory; - if (!isGeneralPurposeLoggingCapable(&drive)){ - pout("Warning: device does not support General Purpose Logging\n"); - } - else { - QUIETON(con); - pout("Log Directory Supported\n"); - if (ataReadLogDirectory(fd, &smartlogdirectory)){ - QUIETOFF(con); - pout("Read Log Directory failed.\n\n"); - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - } - else - ataPrintLogDirectory( &smartlogdirectory); - } - QUIETOFF(con); - } - - // Print SMART error log - if (con->smarterrorlog){ - if (!isSmartErrorLogCapable(&smartval)){ - pout("Warning: device does not support Error Logging\n"); - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - } - else { - if (ataReadErrorLog(fd, &smarterror)){ - pout("Smartctl: SMART Errorlog Read Failed\n"); - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - } - else { - // quiet mode is turned on inside ataPrintSmartErrorLog() - if (ataPrintSmartErrorlog(&smarterror)) - returnval|=FAILERR; - QUIETOFF(con); - } - } - } - - // Print SMART self-test log - if (con->smartselftestlog){ - // Note that in spite of its name, isSmartErrorLogCapable() is - // the CORRECT way to see if a device supports the self-test log. - // The ATA spec says "if this command (READ LOG) is implemented, - // all address values for which the contents are defined shall be - // implemented...". Since both the SMART self-test logs AND the - // SMART error logs are defined, if one will work then so will the - // other. - if (!isSmartErrorLogCapable(&smartval)){ - pout("Warning: device does not support Self Test Logging\n"); - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - } - else { - if(ataReadSelfTestLog(fd, &smartselftest)){ - pout("Smartctl: SMART Self Test Log Read Failed\n"); - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - } - else { - QUIETON(con); - if (ataPrintSmartSelfTestlog(&smartselftest,!con->quietmode)) - returnval|=FAILLOG; - QUIETOFF(con); - pout("\n"); - } - } - } - - // START OF THE TESTING SECTION OF THE CODE. IF NO TESTING, RETURN - if (con->testcase==-1) - return returnval; - - pout("=== START OF OFFLINE IMMEDIATE AND SELF-TEST SECTION ===\n"); - // if doing a self-test, be sure it's supported by the hardware - if (con->testcase==OFFLINE_FULL_SCAN && !isSupportExecuteOfflineImmediate(&smartval)){ - pout("Warning: device does not support Execute Off-Line Immediate function.\n\n"); - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - } - else if (!isSupportSelfTest(&smartval)){ - pout("Warning: device does not support Self-Test functions.\n\n"); - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - } - // Now do the test. Note ataSmartTest prints its own error/success - // messages - if (ataSmartTest(fd, con->testcase)) - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - - // Tell user how long test will take to complete. This is tricky - // because in the case of an Offline Full Scan, the completion timer - // is volatile, and needs to be read AFTER the command is given. If - // this will interrupt the Offline Full Scan, we don't do it, just - // warn user. - if (con->testcase==OFFLINE_FULL_SCAN){ - if (isSupportOfflineAbort(&smartval)) - pout("Note: giving further SMART commands will abort Offline testing\n"); - else if (ataReadSmartValues(fd, &smartval)){ - pout("Smartctl: SMART Read Values failed.\n"); - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - } - } - - // Now say how long the test will take to complete - if ((timewait=TestTime(&smartval,con->testcase))){ - pout("Please wait %d %s for test to complete.\n", - (int)timewait, con->testcase==OFFLINE_FULL_SCAN?"seconds":"minutes"); - - if (con->testcase!=SHORT_CAPTIVE_SELF_TEST && con->testcase!=EXTEND_CAPTIVE_SELF_TEST) - pout("Use smartctl -X to abort test.\n"); - } - return returnval; -} diff --git a/sm5/ataprint.h b/sm5/ataprint.h deleted file mode 100644 index 5dbfd6b28..000000000 --- a/sm5/ataprint.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * ataprint.h - * - * Home page of code is: http://smartmontools.sourceforge.net - * - * Copyright (C) 2002-3 Bruce Allen <smartmontools-support@lists.sourceforge.net> - * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org> - * - * 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 Software Foundation; either version 2, or (at your option) - * any later version. - * - * You should have received a copy of the GNU General Public License - * (for example COPYING); if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * This code was originally developed as a Senior Thesis by Michael Cornwell - * at the Concurrent Systems Laboratory (now part of the Storage Systems - * Research Center), Jack Baskin School of Engineering, University of - * California, Santa Cruz. http://ssrc.soe.ucsc.edu/ - * - */ - -#ifndef _SMART_PRINT_H_ -#define _SMART_PRINT_H_ - -#ifndef ATAPRINT_H_CVSID -#define ATAPRINT_H_CVSID "$Id: ataprint.h,v 1.20 2003/04/18 12:37:14 ballen4705 Exp $\n" -#endif - -#include <stdio.h> -#include <stdlib.h> - -// MACROS to control printing behavior -#define QUIETON(control) {if (control->quietmode) control->veryquietmode=0;} -#define QUIETOFF(control) {if (control->quietmode && !control->veryquietmode) control->veryquietmode=1;} - - - - -/* Prints ATA Drive Information and S.M.A.R.T. Capability */ -void ataPrintDriveInfo(struct hd_driveid *); - -void ataPrintGeneralSmartValues(struct ata_smart_values *, struct hd_driveid *); - -void ataPrintSmartThresholds(struct ata_smart_thresholds *); - -// returns number of errors in Errorlog -int ataPrintSmartErrorlog(struct ata_smart_errorlog *); - -int ataPrintLogDirectory(struct ata_smart_log_directory *); - -void PrintSmartAttributes(struct ata_smart_values *); - -void PrintSmartAttribWithThres(struct ata_smart_values *, - struct ata_smart_thresholds *, - int onlyfailed); - -// returns number of entries that had logged errors -int ataPrintSmartSelfTestlog(struct ata_smart_selftestlog *, int allentries); - -void ataPseudoCheckSmart(struct ata_smart_values *, struct ata_smart_thresholds *); - -// Convenience function for formatting strings from hd_driveid. -void formatdriveidstring(char *out, const char *in, int n); - -int ataPrintMain(int fd); - -#endif diff --git a/sm5/cvs-script b/sm5/cvs-script deleted file mode 100755 index 6974e72e2..000000000 --- a/sm5/cvs-script +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -# execute this script in the current shell, using for example -# . cvs_script -unset CVS_SERVER -export CVS_RSH=ssh -export CVSROOT=:ext:ballen4705@cvs.smartmontools.sourceforge.net:/cvsroot/smartmontools diff --git a/sm5/examplescripts/Example1 b/sm5/examplescripts/Example1 deleted file mode 100755 index 5efb0287c..000000000 --- a/sm5/examplescripts/Example1 +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash -# -# This is a script from the smartmontools examplescripts/ directory. -# It can be used as an argument to the -M exec Directive in -# /etc/smartd.conf, in a line like -# -m root@localhost -M exec /path/to/this/file -# -# Please see man 8 smartd or man 5 smartd.conf for further -# information. -# -# $Id: Example1,v 1.2 2003/02/12 20:01:45 ballen4705 Exp $ - -# Save standard input into a temp file -cat > /root/tempfile - -# Echo command line arguments into temp file -echo "Command line argument 1:" >> /root/tempfile -echo $1 >> /root/tempfile -echo "Command line argument 2:" >> /root/tempfile -echo $2 >> /root/tempfile -echo "Command line argument 3:" >> /root/tempfile -echo $3 >> /root/tempfile - -# Echo environment variables into a temp file -echo "Variables are": >> /root/tempfile -echo "$SMARTD_DEVICE" >> /root/tempfile -echo "$SMARTD_DEVICETYPE" >> /root/tempfile -echo "$SMARTD_MESSAGE" >> /root/tempfile -echo "$SMARTD_ADDRESS" >> /root/tempfile -echo "$SMARTD_SUBJECT" >> /root/tempfile -echo "$SMARTD_TFIRST" >> /root/tempfile -echo "$SMARTD_TFIRSTEPOCH" >> /root/tempfile - -# Run smartctl -a and save output in temp file -/usr/sbin/smartctl -a $SMARTD_DEVICE >> /root/tempfile - -# Email the contents of the temp file -/bin/mail -s "SMART errors detected on host: `hostname`" $SMARTD_ADDRESS < /root/tempfile > /dev/null 2> /dev/null - -# And exit -exit 0 diff --git a/sm5/examplescripts/Example2 b/sm5/examplescripts/Example2 deleted file mode 100755 index 754dc9a26..000000000 --- a/sm5/examplescripts/Example2 +++ /dev/null @@ -1,21 +0,0 @@ -#! /bin/bash -# -# This is a script from the smartmontools examplescripts/ directory. -# It can be used as an argument to the -M exec Directive in -# /etc/smartd.conf, in a line like -# -m root@localhost -M exec /path/to/this/file -# -# Please see man 8 smartd or man 5 smartd.conf for further -# information. -# -# $Id: Example2,v 1.2 2003/02/12 20:01:45 ballen4705 Exp $ - -# Save the email message (STDIN) to a file: -cat > /root/msg - -# Append the output of smartctl -a to the message: -/usr/sbin/smartctl -a $SMARTD_DEVICE >> /root/msg - -# Now email the message to the user at address ADD: -/bin/mail -s "$SMARTD_SUBJECT" $SMARTD_ADDRESS < /root/msg - diff --git a/sm5/examplescripts/Example3 b/sm5/examplescripts/Example3 deleted file mode 100755 index 12b6660e0..000000000 --- a/sm5/examplescripts/Example3 +++ /dev/null @@ -1,25 +0,0 @@ -#! /bin/bash -# -# This is a script from the smartmontools examplescripts/ directory. -# It can be used as an argument to the -M exec Directive in -# /etc/smartd.conf, in a line like -# -m <nomailer> -M exec /path/to/this/file -# -# Please see man 8 smartd or man 5 smartd.conf for further -# information. -# -# $Id: Example3,v 1.2 2003/02/12 20:01:45 ballen4705 Exp $ - -# Warn all users of a problem -wall 'Problem detected with disk: ' $SMARTD_DEVICE -wall 'Warning message from smartd is: ' "$SMARTD_MESSAGE" -wall 'Shutting down machine in 30 seconds... ' - -# Wait half a minute -sleep 30 - -# Power down the machine (uncomment the shutdown command if you really -# want to do this!) - -# /usr/sbin/shutdown -hf now - diff --git a/sm5/examplescripts/README b/sm5/examplescripts/README deleted file mode 100644 index dd6cc2f5b..000000000 --- a/sm5/examplescripts/README +++ /dev/null @@ -1,50 +0,0 @@ -# Home page: http://smartmontools.sourceforge.net -# -# $Id: README,v 1.1 2003/02/12 19:58:33 ballen4705 Exp $ -# -# Copyright (C) 2002 Bruce Allen <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 the Free -# Software Foundation; either version 2, or (at your option) any later -# version. -# -# You should have received a copy of the GNU General Public License (for -# example COPYING); if not, write to the Free Software Foundation, Inc., 675 -# Mass Ave, Cambridge, MA 02139, USA. -# -# This code was originally developed as a Senior Thesis by Michael Cornwell -# at the Concurrent Systems Laboratory (now part of the Storage Systems -# Research Center), Jack Baskin School of Engineering, University of -# California, Santa Cruz. http://ssrc.soe.ucsc.edu/ - -This directory contains executable bash scripts, that are intended for -use with the - -m address -M exec /path/to/an/executable -Directive in /etc/smartd.conf. - -Details about how to use this Directive may be found in the man pages for -smartd and smartd.conf. - man 8 smartd - man 5 smartd.conf -should display those pages on your system. - -If you wish to contribute additional scripts to this collection, -please email them to <smartmontools-support@lists.sourceforge.net>, -and include a one-line description to use below. - -The files contained in this directory are: - -Example1: appends values of $SMARTD_* environment variables and the output - of smartctl -a to the normal email message, and sends that - to the email address listed as the argument to the -m - Directive. - -Example2: Appends output of smartctl -a to the normal email message - and sends that to the email address listed as the argument - to the -m Directive. - -Example3: Uses wall(1) to send a warning message to all users, then powers - down the machine. - - diff --git a/sm5/extern.h b/sm5/extern.h deleted file mode 100644 index 74c7cb89a..000000000 --- a/sm5/extern.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * extern.h - * - * Home page of code is: http://smartmontools.sourceforge.net - * - * Copyright (C) 2002-3 Bruce Allen <smartmontools-support@lists.sourceforge.net> - * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org> - * - * 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 Software Foundation; either version 2, or (at your option) - * any later version. - * - * You should have received a copy of the GNU General Public License - * (for example COPYING); if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * This code was originally developed as a Senior Thesis by Michael Cornwell - * at the Concurrent Systems Laboratory (now part of the Storage Systems - * Research Center), Jack Baskin School of Engineering, University of - * California, Santa Cruz. http://ssrc.soe.ucsc.edu/ - * - */ - -#ifndef _EXTERN_H_ -#define _EXTERN_H_ - - -#ifndef EXTERN_H_CVSID -#define EXTERN_H_CVSID "$Id: extern.h,v 1.24 2003/04/19 09:53:41 pjwilliams Exp $\n" -#endif - -// Possible values for fixfirmwarebug -#define FIX_NONE 0 -#define FIX_SAMSUNG 1 - -// Block used for global control/communications. If you need more -// global variables, this should be the only place that you need to -// add them. -typedef struct smartmonctrl_s { - unsigned char driveinfo; - unsigned char checksmart; - unsigned char smartvendorattrib; - unsigned char generalsmartvalues; - unsigned char smartlogdirectory; - unsigned char smartselftestlog; - unsigned char smarterrorlog; - unsigned char smartdisable; - unsigned char smartenable; - unsigned char smartstatus; - unsigned char smartexeoffimmediate; - unsigned char smartshortselftest; - unsigned char smartextendselftest; - unsigned char smartshortcapselftest; - unsigned char smartextendcapselftest; - unsigned char smartselftestabort; - unsigned char smartautoofflineenable; - unsigned char smartautoofflinedisable; - unsigned char smartautosaveenable; - unsigned char smartautosavedisable; - int testcase; - unsigned char quietmode; - unsigned char veryquietmode; - unsigned char permissive; - unsigned char conservative; - unsigned char checksumfail; - unsigned char checksumignore; - unsigned char reportataioctl; - unsigned char reportscsiioctl; - unsigned char fixfirmwarebug; - unsigned char ignorepresets; - unsigned char showpresets; - // 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]; -} smartmonctrl; - -#endif diff --git a/sm5/knowndrives.c b/sm5/knowndrives.c deleted file mode 100644 index 84698b1a9..000000000 --- a/sm5/knowndrives.c +++ /dev/null @@ -1,412 +0,0 @@ -/* - * knowndrives.c - * - * Home page of code is: http://smartmontools.sourceforge.net - * Address of support mailing list: smartmontools-support@lists.sourceforge.net - * - * Copyright (C) 2003 Philip Williams, Bruce Allen - * - * 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 Software Foundation; either version 2, or (at your option) - * any later version. - * - * You should have received a copy of the GNU General Public License - * (for example COPYING); if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include <stdio.h> -#include <regex.h> -#include "atacmds.h" -#include "ataprint.h" -#include "knowndrives.h" -#include "utility.h" - -const char *knowndrives_c_cvsid="$Id: knowndrives.c,v 1.21 2003/04/22 03:13:43 ballen4705 Exp $" ATACMDS_H_CVSID ATAPRINT_H_CVSID KNOWNDRIVES_H_CVSID UTILITY_H_CVSID; - -#define MODEL_STRING_LENGTH 40 -#define FIRMWARE_STRING_LENGTH 8 -#define TABLEPRINTWIDTH 19 - -// See vendorattributeargs[] array in atacmds.c for definitions. -#define PRESET_9_MINUTES { 9, 1 } -#define PRESET_9_TEMP { 9, 2 } -#define PRESET_9_SECONDS { 9, 3 } -#define PRESET_9_HALFMINUTES { 9, 4 } -#define PRESET_194_10XCELSIUS { 194, 1 } -#define PRESET_194_UNKNOWN { 194, 2 } -#define PRESET_200_WRITEERRORCOUNT { 200, 1 } -#define PRESET_220_TEMP { 220, 1 } - -/* Arrays of preset vendor-specific attribute options for use in - * knowndrives[]. */ - -// This one is common to several models. -const unsigned char vendoropts_9_minutes[][2] = { - PRESET_9_MINUTES, - {0,0} -}; - -const unsigned char vendoropts_Maxtor_4D080H4[][2] = { - PRESET_9_MINUTES, - PRESET_194_UNKNOWN, - {0,0} -}; - -const unsigned char vendoropts_Fujitsu_MPE3204AT[][2] = { - PRESET_9_SECONDS, - {0,0} -}; - -const unsigned char vendoropts_Fujitsu_MHS2020AT[][2] = { - PRESET_200_WRITEERRORCOUNT, - {0,0} -}; - -const unsigned char vendoropts_Samsung_SV4012H[][2] = { - PRESET_9_HALFMINUTES, - {0,0} -}; - -const unsigned char vendoropts_Samsung_SV1204H[][2] = { - PRESET_9_HALFMINUTES, - PRESET_194_10XCELSIUS, - {0,0} -}; - -/* Special-purpose functions for use in knowndrives[]. */ -void specialpurpose_reverse_samsung(smartmonctrl *con) -{ - con->fixfirmwarebug = FIX_SAMSUNG; -} - -/* Table of settings for known drives terminated by an element containing all - * zeros. The drivesettings structure is described in knowndrives.h. Note - * that lookupdrive() will search knowndrives[] from the start to end or - * until it finds the first match, so the order in knowndrives[] is important - * for distinct entries that could match the same drive. */ - -// Note that the table just below uses EXTENDED REGULAR EXPRESSIONS. -// A good on-line reference for these is: -// http://www.zeus.com/extra/docsystem/docroot/apps/web/docs/modules/access/regex.html - -const drivesettings knowndrives[] = { - { // IBM Deskstar 60GXP series - "IC35L0[12346]0AVER07", - ".*", - "IBM Deskstar 60GXP drives may need upgraded SMART firmware.\n" - "Please see http://www.geocities.com/dtla_update/index.html#rel", - NULL, NULL, NULL - }, - { // IBM Deskstar 40GV & 75GXP series - "(IBM-)?DTLA-30[57]0[123467][05]$", - ".*", - "IBM Deskstar 40GV and 75GXP drives may need upgraded SMART firmware.\n" - "Please see http://www.geocities.com/dtla_update/", - NULL, NULL, NULL - }, - { // Fujitsu MPE3204AT - "^FUJITSU MPE3204AT$", - ".*", // Tested on ED-03-04 - NULL, - vendoropts_Fujitsu_MPE3204AT, - NULL, NULL - }, - { // Fujitsu MHS2020AT - "^FUJITSU MHS2020AT$", - ".*", // Tested on 8004 - NULL, - vendoropts_Fujitsu_MHS2020AT, - NULL, NULL - }, - { // Samsung SV4012H (known firmware) - "^SAMSUNG SV4012H$", - "^RM100-08", - NULL, - vendoropts_Samsung_SV4012H, - specialpurpose_reverse_samsung, - "Fixes byte order in some SMART data (same as -F)" - }, - { // Samsung SV4012H (all other firmware) - "^SAMSUNG SV4012H$", - ".*", - "Contact developers; may need -F disabled", - vendoropts_Samsung_SV4012H, - specialpurpose_reverse_samsung, - "Fixes byte order in some SMART data (same as -F)" - }, - { // Samsung SV1204H (known firmware) - "^SAMSUNG SV1204H$", - "^RK100-1[3-5]$", - NULL, - vendoropts_Samsung_SV1204H, - specialpurpose_reverse_samsung, - "Fixes byte order in some SMART data (same as -F)" - }, - { //Samsung SV1204H (all other firmware) - "^SAMSUNG SV1204H$", - ".*", - "Contact developers; may need -F disabled", - vendoropts_Samsung_SV1204H, - specialpurpose_reverse_samsung, - "Fixes byte order in some SMART data (same as -F)" - }, - { // Samsung ALL OTHER DRIVES - "^SAMSUNG.*", - ".*", - "Contact developers; may need -F enabled.\n", - NULL, NULL, NULL - }, - { // Maxtor 6L080J4 and 4K080H4 - "^MAXTOR (6L080J4|4K080H4)$", - ".*", - NULL, NULL, NULL, NULL - }, - { // Maxtor 4D080H4 - "^Maxtor 4D080H4$", - ".*", - NULL, - vendoropts_Maxtor_4D080H4, - NULL, NULL - }, - { // Maxtor 4R080J0 - "^Maxtor 4R080J0$", - ".*", - NULL, - vendoropts_9_minutes, - NULL, NULL - }, - { // Maxtor 6Y120P0 (known firmware) - "^Maxtor 6Y120P0$", - "^YAR41VW0$", - NULL, - vendoropts_9_minutes, - NULL, NULL - }, - { // Maxtor 6Y120P0 (any other firmware) - "^Maxtor 6Y120P0$", - ".*", - "Contact developers; may need -v 9,minutes enabled.\n", - NULL, - NULL, NULL - }, - { // HITACHI_DK23BA-20 - "^HITACHI_DK23BA-20$", - ".*", - NULL, - vendoropts_9_minutes, - NULL, NULL - }, - { // IBM GXP-180 - "^IC35L120AVV207-0$", - ".*", - NULL, NULL, NULL, NULL - }, - { - // IBM Deskstar 120GXP [Phil -- use for testing] - "^IC35L060AVVA07-0$", - ".*", - NULL, - NULL, - NULL, - NULL, - }, - { - // TOSHIBA MK6021GAS [Bruce -- use for testing on laptop] - "^TOSHIBA MK6021GAS$", - ".*", - NULL, - NULL, - NULL, - NULL, - }, - /*------------------------------------------------------------ - * End of table. Do not add entries below this marker. - *------------------------------------------------------------ */ - {NULL, NULL, NULL, NULL, NULL} -}; - -// Searches knowndrives[] for a drive with the given model number and firmware -// string. If either the drive's model or firmware strings are not set by the -// manufacturer then values of NULL may be used. Returns the index of the -// first match in knowndrives[] or -1 if no match if found. -int lookupdrive(const char *model, const char *firmware) -{ - regex_t regex; - int i, index; - const char *empty = ""; - - model = model ? model : empty; - firmware = firmware ? firmware : empty; - - for (i = 0, index = -1; index == -1 && knowndrives[i].modelregexp; i++) { - // Attempt to compile regular expression. - if (compileregex(®ex, knowndrives[i].modelregexp, REG_EXTENDED)) - goto CONTINUE; - - // Check whether model matches the regular expression in knowndrives[i]. - if (!regexec(®ex, model, 0, NULL, 0)) { - // model matches, now check firmware. - if (!knowndrives[i].firmwareregexp) - // The firmware regular expression in knowndrives[i] is NULL, which is - // considered a match. - index = i; - else { - // Compare firmware against the regular expression in knowndrives[i]. - regfree(®ex); // Recycle regex. - if (compileregex(®ex, knowndrives[i].firmwareregexp, REG_EXTENDED)) - goto CONTINUE; - if (!regexec(®ex, firmware, 0, NULL, 0)) - index = i; - } - } - CONTINUE: - regfree(®ex); - } - - return index; -} - - -// Shows all presets for drives in knowndrives[]. -void showonepreset(const drivesettings *drivetable){ - - const unsigned char (* presets)[2] = drivetable->vendoropts; - int first_preset = 1; - - // Basic error check - if (!drivetable || !drivetable->modelregexp){ - pout("Null known drive table pointer. Please report\n" - "this error to smartmontools developers.\n"); - return; - } - - // print model and firmware regular expressions - pout("%-*s %s\n", TABLEPRINTWIDTH, "MODEL REGEXP:", drivetable->modelregexp); - pout("%-*s %s\n", TABLEPRINTWIDTH, "FIRMWARE REGEXP:", drivetable->firmwareregexp ? - drivetable->firmwareregexp : ""); - - // if there are any presets, then show them - if (presets && (*presets)[0]) while (1) { - char out[64]; - const int attr = (*presets)[0], val = (*presets)[1]; - - // if we are at the end of the attribute list, break out - if (!attr) - break; - - ataPrintSmartAttribName(out, attr, val); - // 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); - first_preset = 0; - presets++; - } - else - pout("%-*s %s\n", TABLEPRINTWIDTH, "ATTRIBUTE OPTIONS:", "None preset; no -v options are required."); - - - // Is a special purpose function defined? If so, describe it - if (drivetable->specialpurpose){ - pout("%-*s ", TABLEPRINTWIDTH, "OTHER PRESETS:"); - pout("%s\n", drivetable->functiondesc ? - drivetable->functiondesc : "A special purpose function " - "is defined for this drive"); - } - - // Print any special warnings - if (drivetable->warningmsg){ - pout("%-*s ", TABLEPRINTWIDTH, "WARNINGS:"); - pout("%s\n", drivetable->warningmsg); - } - - return; -} - -void showallpresets(void){ - int i; - - // loop over all entries in the knowndrives[] table, printing them - // out in a nice format - for (i=0; knowndrives[i].modelregexp; i++){ - showonepreset(&knowndrives[i]); - pout("\n"); - } - return; -} - -// Shows the presets (if any) that are available for the given drive. -void showpresets(const struct hd_driveid *drive){ - int i; - char model[MODEL_STRING_LENGTH+1], firmware[FIRMWARE_STRING_LENGTH+1]; - - // get the drive's model/firmware strings - formatdriveidstring(model, drive->model, MODEL_STRING_LENGTH); - formatdriveidstring(firmware, drive->fw_rev, FIRMWARE_STRING_LENGTH); - - // and search to see if they match values in the table - if ((i = lookupdrive(model, firmware)) < 0) { - // no matches found - pout("No presets are defined for this drive. Its identity strings:\n" - "MODEL: %s\n" - "FIRMWARE: %s\n" - "do not match any of the known regular expressions.\n" - "Use -P showall to list all known regular expressions.\n", - model, firmware); - return; - } - - // We found a matching drive. Print out all information about it. - pout("Drive found in smartmontools Database. Drive identity strings:\n" - "%-*s %s\n" - "%-*s %s\n" - "match smartmontools Drive Database entry:\n", - TABLEPRINTWIDTH, "MODEL:", model, TABLEPRINTWIDTH, "FIRMWARE:", firmware); - showonepreset(&knowndrives[i]); - return; -} - -// Sets preset vendor attribute options in opts by finding the entry -// (if any) for the given drive in knowndrives[]. Values that have -// already been set in opts will not be changed. Returns <0 if drive -// not recognized else index >=0 into drive database. -int applypresets(const struct hd_driveid *drive, unsigned char opts[256], - smartmonctrl *con) { - int i; - char model[MODEL_STRING_LENGTH+1], firmware[FIRMWARE_STRING_LENGTH+1]; - - // get the drive's model/firmware strings - formatdriveidstring(model, drive->model, MODEL_STRING_LENGTH); - formatdriveidstring(firmware, drive->fw_rev, FIRMWARE_STRING_LENGTH); - - // Look up the drive in knowndrives[] and check vendoropts is non-NULL. - if ((i = lookupdrive(model, firmware)) >= 0 && knowndrives[i].vendoropts) { - const unsigned char (* presets)[2]; - - // For each attribute in list of attribute/val pairs... - presets = knowndrives[i].vendoropts; - while (1) { - const int attr = (*presets)[0]; - const int val = (*presets)[1]; - - if (!attr) - break; - - // ... set attribute if user hasn't already done so. - if (!opts[attr]) - opts[attr] = val; - presets++; - } - - // If a function is defined for this drive then call it. - if (knowndrives[i].specialpurpose) - (*knowndrives[i].specialpurpose)(con); - } - - // return <0 if drive wasn't recognized, or index>=0 into database - // if it was - return i; -} diff --git a/sm5/knowndrives.cpp b/sm5/knowndrives.cpp deleted file mode 100644 index 3375167e1..000000000 --- a/sm5/knowndrives.cpp +++ /dev/null @@ -1,412 +0,0 @@ -/* - * knowndrives.c - * - * Home page of code is: http://smartmontools.sourceforge.net - * Address of support mailing list: smartmontools-support@lists.sourceforge.net - * - * Copyright (C) 2003 Philip Williams, Bruce Allen - * - * 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 Software Foundation; either version 2, or (at your option) - * any later version. - * - * You should have received a copy of the GNU General Public License - * (for example COPYING); if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include <stdio.h> -#include <regex.h> -#include "atacmds.h" -#include "ataprint.h" -#include "knowndrives.h" -#include "utility.h" - -const char *knowndrives_c_cvsid="$Id: knowndrives.cpp,v 1.21 2003/04/22 03:13:43 ballen4705 Exp $" ATACMDS_H_CVSID ATAPRINT_H_CVSID KNOWNDRIVES_H_CVSID UTILITY_H_CVSID; - -#define MODEL_STRING_LENGTH 40 -#define FIRMWARE_STRING_LENGTH 8 -#define TABLEPRINTWIDTH 19 - -// See vendorattributeargs[] array in atacmds.c for definitions. -#define PRESET_9_MINUTES { 9, 1 } -#define PRESET_9_TEMP { 9, 2 } -#define PRESET_9_SECONDS { 9, 3 } -#define PRESET_9_HALFMINUTES { 9, 4 } -#define PRESET_194_10XCELSIUS { 194, 1 } -#define PRESET_194_UNKNOWN { 194, 2 } -#define PRESET_200_WRITEERRORCOUNT { 200, 1 } -#define PRESET_220_TEMP { 220, 1 } - -/* Arrays of preset vendor-specific attribute options for use in - * knowndrives[]. */ - -// This one is common to several models. -const unsigned char vendoropts_9_minutes[][2] = { - PRESET_9_MINUTES, - {0,0} -}; - -const unsigned char vendoropts_Maxtor_4D080H4[][2] = { - PRESET_9_MINUTES, - PRESET_194_UNKNOWN, - {0,0} -}; - -const unsigned char vendoropts_Fujitsu_MPE3204AT[][2] = { - PRESET_9_SECONDS, - {0,0} -}; - -const unsigned char vendoropts_Fujitsu_MHS2020AT[][2] = { - PRESET_200_WRITEERRORCOUNT, - {0,0} -}; - -const unsigned char vendoropts_Samsung_SV4012H[][2] = { - PRESET_9_HALFMINUTES, - {0,0} -}; - -const unsigned char vendoropts_Samsung_SV1204H[][2] = { - PRESET_9_HALFMINUTES, - PRESET_194_10XCELSIUS, - {0,0} -}; - -/* Special-purpose functions for use in knowndrives[]. */ -void specialpurpose_reverse_samsung(smartmonctrl *con) -{ - con->fixfirmwarebug = FIX_SAMSUNG; -} - -/* Table of settings for known drives terminated by an element containing all - * zeros. The drivesettings structure is described in knowndrives.h. Note - * that lookupdrive() will search knowndrives[] from the start to end or - * until it finds the first match, so the order in knowndrives[] is important - * for distinct entries that could match the same drive. */ - -// Note that the table just below uses EXTENDED REGULAR EXPRESSIONS. -// A good on-line reference for these is: -// http://www.zeus.com/extra/docsystem/docroot/apps/web/docs/modules/access/regex.html - -const drivesettings knowndrives[] = { - { // IBM Deskstar 60GXP series - "IC35L0[12346]0AVER07", - ".*", - "IBM Deskstar 60GXP drives may need upgraded SMART firmware.\n" - "Please see http://www.geocities.com/dtla_update/index.html#rel", - NULL, NULL, NULL - }, - { // IBM Deskstar 40GV & 75GXP series - "(IBM-)?DTLA-30[57]0[123467][05]$", - ".*", - "IBM Deskstar 40GV and 75GXP drives may need upgraded SMART firmware.\n" - "Please see http://www.geocities.com/dtla_update/", - NULL, NULL, NULL - }, - { // Fujitsu MPE3204AT - "^FUJITSU MPE3204AT$", - ".*", // Tested on ED-03-04 - NULL, - vendoropts_Fujitsu_MPE3204AT, - NULL, NULL - }, - { // Fujitsu MHS2020AT - "^FUJITSU MHS2020AT$", - ".*", // Tested on 8004 - NULL, - vendoropts_Fujitsu_MHS2020AT, - NULL, NULL - }, - { // Samsung SV4012H (known firmware) - "^SAMSUNG SV4012H$", - "^RM100-08", - NULL, - vendoropts_Samsung_SV4012H, - specialpurpose_reverse_samsung, - "Fixes byte order in some SMART data (same as -F)" - }, - { // Samsung SV4012H (all other firmware) - "^SAMSUNG SV4012H$", - ".*", - "Contact developers; may need -F disabled", - vendoropts_Samsung_SV4012H, - specialpurpose_reverse_samsung, - "Fixes byte order in some SMART data (same as -F)" - }, - { // Samsung SV1204H (known firmware) - "^SAMSUNG SV1204H$", - "^RK100-1[3-5]$", - NULL, - vendoropts_Samsung_SV1204H, - specialpurpose_reverse_samsung, - "Fixes byte order in some SMART data (same as -F)" - }, - { //Samsung SV1204H (all other firmware) - "^SAMSUNG SV1204H$", - ".*", - "Contact developers; may need -F disabled", - vendoropts_Samsung_SV1204H, - specialpurpose_reverse_samsung, - "Fixes byte order in some SMART data (same as -F)" - }, - { // Samsung ALL OTHER DRIVES - "^SAMSUNG.*", - ".*", - "Contact developers; may need -F enabled.\n", - NULL, NULL, NULL - }, - { // Maxtor 6L080J4 and 4K080H4 - "^MAXTOR (6L080J4|4K080H4)$", - ".*", - NULL, NULL, NULL, NULL - }, - { // Maxtor 4D080H4 - "^Maxtor 4D080H4$", - ".*", - NULL, - vendoropts_Maxtor_4D080H4, - NULL, NULL - }, - { // Maxtor 4R080J0 - "^Maxtor 4R080J0$", - ".*", - NULL, - vendoropts_9_minutes, - NULL, NULL - }, - { // Maxtor 6Y120P0 (known firmware) - "^Maxtor 6Y120P0$", - "^YAR41VW0$", - NULL, - vendoropts_9_minutes, - NULL, NULL - }, - { // Maxtor 6Y120P0 (any other firmware) - "^Maxtor 6Y120P0$", - ".*", - "Contact developers; may need -v 9,minutes enabled.\n", - NULL, - NULL, NULL - }, - { // HITACHI_DK23BA-20 - "^HITACHI_DK23BA-20$", - ".*", - NULL, - vendoropts_9_minutes, - NULL, NULL - }, - { // IBM GXP-180 - "^IC35L120AVV207-0$", - ".*", - NULL, NULL, NULL, NULL - }, - { - // IBM Deskstar 120GXP [Phil -- use for testing] - "^IC35L060AVVA07-0$", - ".*", - NULL, - NULL, - NULL, - NULL, - }, - { - // TOSHIBA MK6021GAS [Bruce -- use for testing on laptop] - "^TOSHIBA MK6021GAS$", - ".*", - NULL, - NULL, - NULL, - NULL, - }, - /*------------------------------------------------------------ - * End of table. Do not add entries below this marker. - *------------------------------------------------------------ */ - {NULL, NULL, NULL, NULL, NULL} -}; - -// Searches knowndrives[] for a drive with the given model number and firmware -// string. If either the drive's model or firmware strings are not set by the -// manufacturer then values of NULL may be used. Returns the index of the -// first match in knowndrives[] or -1 if no match if found. -int lookupdrive(const char *model, const char *firmware) -{ - regex_t regex; - int i, index; - const char *empty = ""; - - model = model ? model : empty; - firmware = firmware ? firmware : empty; - - for (i = 0, index = -1; index == -1 && knowndrives[i].modelregexp; i++) { - // Attempt to compile regular expression. - if (compileregex(®ex, knowndrives[i].modelregexp, REG_EXTENDED)) - goto CONTINUE; - - // Check whether model matches the regular expression in knowndrives[i]. - if (!regexec(®ex, model, 0, NULL, 0)) { - // model matches, now check firmware. - if (!knowndrives[i].firmwareregexp) - // The firmware regular expression in knowndrives[i] is NULL, which is - // considered a match. - index = i; - else { - // Compare firmware against the regular expression in knowndrives[i]. - regfree(®ex); // Recycle regex. - if (compileregex(®ex, knowndrives[i].firmwareregexp, REG_EXTENDED)) - goto CONTINUE; - if (!regexec(®ex, firmware, 0, NULL, 0)) - index = i; - } - } - CONTINUE: - regfree(®ex); - } - - return index; -} - - -// Shows all presets for drives in knowndrives[]. -void showonepreset(const drivesettings *drivetable){ - - const unsigned char (* presets)[2] = drivetable->vendoropts; - int first_preset = 1; - - // Basic error check - if (!drivetable || !drivetable->modelregexp){ - pout("Null known drive table pointer. Please report\n" - "this error to smartmontools developers.\n"); - return; - } - - // print model and firmware regular expressions - pout("%-*s %s\n", TABLEPRINTWIDTH, "MODEL REGEXP:", drivetable->modelregexp); - pout("%-*s %s\n", TABLEPRINTWIDTH, "FIRMWARE REGEXP:", drivetable->firmwareregexp ? - drivetable->firmwareregexp : ""); - - // if there are any presets, then show them - if (presets && (*presets)[0]) while (1) { - char out[64]; - const int attr = (*presets)[0], val = (*presets)[1]; - - // if we are at the end of the attribute list, break out - if (!attr) - break; - - ataPrintSmartAttribName(out, attr, val); - // 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); - first_preset = 0; - presets++; - } - else - pout("%-*s %s\n", TABLEPRINTWIDTH, "ATTRIBUTE OPTIONS:", "None preset; no -v options are required."); - - - // Is a special purpose function defined? If so, describe it - if (drivetable->specialpurpose){ - pout("%-*s ", TABLEPRINTWIDTH, "OTHER PRESETS:"); - pout("%s\n", drivetable->functiondesc ? - drivetable->functiondesc : "A special purpose function " - "is defined for this drive"); - } - - // Print any special warnings - if (drivetable->warningmsg){ - pout("%-*s ", TABLEPRINTWIDTH, "WARNINGS:"); - pout("%s\n", drivetable->warningmsg); - } - - return; -} - -void showallpresets(void){ - int i; - - // loop over all entries in the knowndrives[] table, printing them - // out in a nice format - for (i=0; knowndrives[i].modelregexp; i++){ - showonepreset(&knowndrives[i]); - pout("\n"); - } - return; -} - -// Shows the presets (if any) that are available for the given drive. -void showpresets(const struct hd_driveid *drive){ - int i; - char model[MODEL_STRING_LENGTH+1], firmware[FIRMWARE_STRING_LENGTH+1]; - - // get the drive's model/firmware strings - formatdriveidstring(model, drive->model, MODEL_STRING_LENGTH); - formatdriveidstring(firmware, drive->fw_rev, FIRMWARE_STRING_LENGTH); - - // and search to see if they match values in the table - if ((i = lookupdrive(model, firmware)) < 0) { - // no matches found - pout("No presets are defined for this drive. Its identity strings:\n" - "MODEL: %s\n" - "FIRMWARE: %s\n" - "do not match any of the known regular expressions.\n" - "Use -P showall to list all known regular expressions.\n", - model, firmware); - return; - } - - // We found a matching drive. Print out all information about it. - pout("Drive found in smartmontools Database. Drive identity strings:\n" - "%-*s %s\n" - "%-*s %s\n" - "match smartmontools Drive Database entry:\n", - TABLEPRINTWIDTH, "MODEL:", model, TABLEPRINTWIDTH, "FIRMWARE:", firmware); - showonepreset(&knowndrives[i]); - return; -} - -// Sets preset vendor attribute options in opts by finding the entry -// (if any) for the given drive in knowndrives[]. Values that have -// already been set in opts will not be changed. Returns <0 if drive -// not recognized else index >=0 into drive database. -int applypresets(const struct hd_driveid *drive, unsigned char opts[256], - smartmonctrl *con) { - int i; - char model[MODEL_STRING_LENGTH+1], firmware[FIRMWARE_STRING_LENGTH+1]; - - // get the drive's model/firmware strings - formatdriveidstring(model, drive->model, MODEL_STRING_LENGTH); - formatdriveidstring(firmware, drive->fw_rev, FIRMWARE_STRING_LENGTH); - - // Look up the drive in knowndrives[] and check vendoropts is non-NULL. - if ((i = lookupdrive(model, firmware)) >= 0 && knowndrives[i].vendoropts) { - const unsigned char (* presets)[2]; - - // For each attribute in list of attribute/val pairs... - presets = knowndrives[i].vendoropts; - while (1) { - const int attr = (*presets)[0]; - const int val = (*presets)[1]; - - if (!attr) - break; - - // ... set attribute if user hasn't already done so. - if (!opts[attr]) - opts[attr] = val; - presets++; - } - - // If a function is defined for this drive then call it. - if (knowndrives[i].specialpurpose) - (*knowndrives[i].specialpurpose)(con); - } - - // return <0 if drive wasn't recognized, or index>=0 into database - // if it was - return i; -} diff --git a/sm5/knowndrives.h b/sm5/knowndrives.h deleted file mode 100644 index afeeb2565..000000000 --- a/sm5/knowndrives.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * knowndrives.h - * - * Home page of code is: http://smartmontools.sourceforge.net - * Address of support mailing list: smartmontools-support@lists.sourceforge.net - * - * Copyright (C) 2003 Philip Williams, Bruce Allen - * - * 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 Software Foundation; either version 2, or (at your option) - * any later version. - * - * You should have received a copy of the GNU General Public License - * (for example COPYING); if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#ifndef __KNOWNDRIVES_H_ -#define __KNOWNDRIVES_H_ - -#define KNOWNDRIVES_H_CVSID "$Id: knowndrives.h,v 1.6 2003/04/20 15:38:38 ballen4705 Exp $\n" - -#include <linux/hdreg.h> -#include "extern.h" - -/* Structure used to store settings for specific drives in knowndrives[]. The - * elements are used in the following ways: - * - * modelregexp POSIX regular expression to match the model of a device. - * This should never be NULL (except to terminate the - * knowndrives array). - * firmwareregexp POSIX regular expression to match a devices's firmware - * version. This is optional and should be NULL if it is not - * to be used. If it is non-NULL then it will be used to - * narrow the set of devices matched by modelregexp. - * warningmsg A message that may be displayed for matching drives. For - * example, to inform the user that they may need to apply a - * firmware patch. - * vendoropts Pointer to first element of an array of vendor-specific - * option attribute/value pairs that should be set for a - * matching device unless the user has requested otherwise. - * The user's own settings override these. The array should - * be terminated with the entry {0,0}. - * specialpurpose Pointer to a function that defines some additional action - * that may be taken for matching devices. - * functiondesc A description of the effect of the specialpurpose - * function. Used by showpresets() and showallpresets() to - * make the output more informative. - */ -typedef struct drivesettings_s { - const char * const modelregexp; - const char * const firmwareregexp; - const char * const warningmsg; - const unsigned char (* const vendoropts)[2]; - void (* const specialpurpose)(smartmonctrl *); - const char * const functiondesc; -} drivesettings; - -/* Table of settings for known drives. Defined in knowndrives.c. */ -extern const drivesettings knowndrives[]; - -// Searches knowndrives[] for a drive with the given model number and firmware -// string. -int lookupdrive(const char *model, const char *firmware); - -// Shows the presets (if any) that are available for the given drive. -void showpresets(const struct hd_driveid *drive); - -// Shows all presets for drives in knowndrives[]. -void showallpresets(void); - -// Sets preset vendor attribute options in opts by finding the entry -// (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 <0 if drive not recognized else index of drive in -// database. -int applypresets(const struct hd_driveid *drive, unsigned char opts[256], - smartmonctrl *con); - -#endif diff --git a/sm5/scsicmds.c b/sm5/scsicmds.c deleted file mode 100644 index f757f7d6e..000000000 --- a/sm5/scsicmds.c +++ /dev/null @@ -1,1631 +0,0 @@ -/* - * scsicmds.c - * - * Home page of code is: http://smartmontools.sourceforge.net - * - * Copyright (C) 2002-3 Bruce Allen <smartmontools-support@lists.sourceforge.net> - * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org> - * - * Additional SCSI work: - * Copyright (C) 2003 Douglas Gilbert <dougg@torque.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 - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * You should have received a copy of the GNU General Public License - * (for example COPYING); if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * This code was originally developed as a Senior Thesis by Michael Cornwell - * at the Concurrent Systems Laboratory (now part of the Storage Systems - * Research Center), Jack Baskin School of Engineering, University of - * California, Santa Cruz. http://ssrc.soe.ucsc.edu/ - * - * - * In the SCSI world "SMART" is a dead or withdrawn standard. In recent - * SCSI standards (since SCSI-3) it goes under the awkward name of - * "Informational Exceptions" ["IE" or "IEC" (with the "C" for "control")]. - * The relevant information is spread around several SCSI draft - * standards available at http://www.t10.org . Reference is made in the - * code to the following acronyms: - * - SAM [SCSI Architectural model, versions 2 or 3] - * - SPC [SCSI Primary commands, versions 2 or 3] - * - SBC [SCSI Block commands, versions 2] - * - * Some SCSI disk vendors have snippets of "SMART" information in their - * product manuals. - */ - -#include <stdio.h> -#include <string.h> -#include <getopt.h> -#include <unistd.h> -#include <sys/ioctl.h> -#include "scsicmds.h" -#include "utility.h" -#include "extern.h" - -const char *scsicmds_c_cvsid="$Id: scsicmds.c,v 1.42 2003/04/29 16:01:09 makisara Exp $" EXTERN_H_CVSID SCSICMDS_H_CVSID; - -/* for passing global control variables */ -extern smartmonctrl *con; - -/* output binary in hex and optionally ascii */ -static void dStrHex(const char* str, int len, int no_ascii) -{ - const char* p = str; - unsigned char c; - char buff[82]; - int a = 0; - const int bpstart = 5; - const int cpstart = 60; - int cpos = cpstart; - int bpos = bpstart; - int i, k; - - if (len <= 0) return; - memset(buff,' ',80); - buff[80]='\0'; - k = sprintf(buff + 1, "%.2x", a); - buff[k + 1] = ' '; - if (bpos >= ((bpstart + (9 * 3)))) - bpos++; - - for(i = 0; i < len; i++) - { - c = *p++; - bpos += 3; - if (bpos == (bpstart + (9 * 3))) - bpos++; - sprintf(&buff[bpos], "%.2x", (int)(unsigned char)c); - buff[bpos + 2] = ' '; - if (no_ascii) - buff[cpos++] = ' '; - else { - if ((c < ' ') || (c >= 0x7f)) - c='.'; - buff[cpos++] = c; - } - if (cpos > (cpstart+15)) - { - pout("%s\n", buff); - bpos = bpstart; - cpos = cpstart; - a += 16; - memset(buff,' ',80); - k = sprintf(buff + 1, "%.2x", a); - buff[k + 1] = ' '; - } - } - if (cpos > cpstart) - { - pout("%s\n", buff); - } -} - -struct scsi_opcode_name { - UINT8 opcode; - const char * name; -}; - -static struct scsi_opcode_name opcode_name_arr[] = { - /* in ascending opcode order */ - {TEST_UNIT_READY, "test unit ready"}, /* 0x00 */ - {REQUEST_SENSE, "request sense"}, /* 0x03 */ - {INQUIRY, "inquiry"}, /* 0x12 */ - {MODE_SELECT, "mode select"}, /* 0x15 */ - {MODE_SENSE, "mode sense"}, /* 0x1a */ - {RECEIVE_DIAGNOSTIC, "receive diagnostic"}, /* 0x1c */ - {SEND_DIAGNOSTIC, "send diagnostic"}, /* 0x1d */ - {LOG_SENSE, "log sense"}, /* 0x4d */ - {MODE_SELECT_10, "mode select(10)"}, /* 0x55 */ - {MODE_SENSE_10, "mode sense(10)"}, /* 0x5a */ -}; - -const char * scsi_get_opcode_name(UINT8 opcode) -{ - int k; - int len = sizeof(opcode_name_arr) / sizeof(opcode_name_arr[0]); - struct scsi_opcode_name * onp; - - for (k = 0; k < len; ++k) { - onp = &opcode_name_arr[k]; - if (opcode == onp->opcode) - return onp->name; - else if (opcode < onp->opcode) - return NULL; - } - return NULL; -} - -/* SCSI command transmission interface function, implementation is OS - * specific. */ -static int do_scsi_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop); - -/* <<<<<<<<<<<<<<<< Start of Linux specific code >>>>>>>>>>>>>>>>> */ -#if 1 -/* Linux specific code, FreeBSD could conditionally compile in CAM stuff - * instead of this. */ - -/* #include <scsi/scsi.h> bypass for now */ -/* #include <scsi/scsi_ioctl.h> bypass for now */ - -#define MAX_DXFER_LEN 1024 /* can be increased if necessary */ -#define SEND_IOCTL_RESP_SENSE_LEN 16 /* ioctl limitation */ -#define DRIVER_SENSE 0x8 /* alternate CHECK CONDITION indication */ - -#ifndef SCSI_IOCTL_SEND_COMMAND -#define SCSI_IOCTL_SEND_COMMAND 1 -#endif -#ifndef SCSI_IOCTL_TEST_UNIT_READY -#define SCSI_IOCTL_TEST_UNIT_READY 2 -#endif - -struct linux_ioctl_send_command -{ - int inbufsize; - int outbufsize; - UINT8 buff[MAX_DXFER_LEN + 16]; -}; - -/* The Linux SCSI_IOCTL_SEND_COMMAND ioctl is primitive and it doesn't - * support: CDB length (guesses it from opcode), resid and timeout. - * Patches pending in Linux 2.4 and 2.5 to extend SEND DIAGNOSTIC timeout - * to 2 hours in order to allow long foreground extended self tests. */ -static int linux_do_scsi_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop) -{ - struct linux_ioctl_send_command wrk; - int status, buff_offset; - size_t len; - - memcpy(wrk.buff, iop->cmnd, iop->cmnd_len); - buff_offset = iop->cmnd_len; - if (con->reportscsiioctl > 0) { - int k; - const unsigned char * ucp = iop->cmnd; - const char * np; - - np = scsi_get_opcode_name(ucp[0]); - pout(" [%s: ", np ? np : "<unknown opcode>"); - for (k = 0; k < iop->cmnd_len; ++k) - pout("%02x ", ucp[k]); - if ((con->reportscsiioctl > 1) && - (DXFER_TO_DEVICE == iop->dxfer_dir) && (iop->dxferp)) { - int trunc = (iop->dxfer_len > 256) ? 1 : 0; - - pout("]\n Outgoing data, len=%d%s:\n", iop->dxfer_len, - (trunc ? " [only first 256 bytes shown]" : "")); - dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1); - } - else - pout("]"); - } - switch (iop->dxfer_dir) { - case DXFER_NONE: - wrk.inbufsize = 0; - wrk.outbufsize = 0; - break; - case DXFER_FROM_DEVICE: - wrk.inbufsize = 0; - if (iop->dxfer_len > MAX_DXFER_LEN) - return -EINVAL; - wrk.outbufsize = iop->dxfer_len; - break; - case DXFER_TO_DEVICE: - if (iop->dxfer_len > MAX_DXFER_LEN) - return -EINVAL; - memcpy(wrk.buff + buff_offset, iop->dxferp, iop->dxfer_len); - wrk.inbufsize = iop->dxfer_len; - wrk.outbufsize = 0; - break; - default: - pout("do_scsi_cmnd_io: bad dxfer_dir\n"); - return -EINVAL; - } - iop->resp_sense_len = 0; - iop->scsi_status = 0; - iop->resid = 0; - status = ioctl(dev_fd, SCSI_IOCTL_SEND_COMMAND , &wrk); - if (-1 == status) { - if (con->reportscsiioctl) - pout(" status=-1, errno=%d [%s]\n", errno, strerror(errno)); - return -errno; - } - if (0 == status) { - if (con->reportscsiioctl > 0) - pout(" status=0\n"); - if (DXFER_FROM_DEVICE == iop->dxfer_dir) { - memcpy(iop->dxferp, wrk.buff, iop->dxfer_len); - if (con->reportscsiioctl > 1) { - int trunc = (iop->dxfer_len > 256) ? 1 : 0; - - pout(" Incoming data, len=%d%s:\n", iop->dxfer_len, - (trunc ? " [only first 256 bytes shown]" : "")); - dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1); - } - } - return 0; - } - iop->scsi_status = status & 0x7e; /* bits 0 and 7 used to be for vendors */ - if (DRIVER_SENSE == ((status >> 24) & 0xff)) - iop->scsi_status = 2; - len = (SEND_IOCTL_RESP_SENSE_LEN < iop->max_sense_len) ? - SEND_IOCTL_RESP_SENSE_LEN : iop->max_sense_len; - if ((SCSI_STATUS_CHECK_CONDITION == iop->scsi_status) && - iop->sensep && (len > 0)) { - memcpy(iop->sensep, wrk.buff, len); - iop->resp_sense_len = len; - if (con->reportscsiioctl > 1) { - pout(" >>> Sense buffer, len=%d:\n", len); - dStrHex(wrk.buff, len , 1); - } - } - if (con->reportscsiioctl) { - if (SCSI_STATUS_CHECK_CONDITION == iop->scsi_status) { - pout(" status=%x: sense_key=%x asc=%x ascq=%x\n", status & 0xff, - wrk.buff[2] & 0xf, wrk.buff[12], wrk.buff[13]); - } - else - pout(" status=0x%x\n", status); - } - if (iop->scsi_status > 0) - return 0; - else { - if (con->reportscsiioctl > 0) - pout(" ioctl status=0x%x but scsi status=0, fail with ENODEV\n", - status); - return -ENODEV; /* give up, assume no device there */ - } -} - -static int do_scsi_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop) -{ - return linux_do_scsi_cmnd_io(dev_fd, iop); -} -#endif -/* <<<<<<<<<<<<<<<< End of Linux specific code >>>>>>>>>>>>>>>>> */ - -void scsi_do_sense_disect(const struct scsi_cmnd_io * io_buf, - struct scsi_sense_disect * out) -{ - memset(out, 0, sizeof(out)); - if ((SCSI_STATUS_CHECK_CONDITION == io_buf->scsi_status) && - (io_buf->resp_sense_len > 7)) { - out->error_code = (io_buf->sensep[0] & 0x7f); - out->sense_key = (io_buf->sensep[2] & 0xf); - if (io_buf->resp_sense_len > 13) { - out->asc = io_buf->sensep[12]; - out->ascq = io_buf->sensep[13]; - } - } -} - -static int scsiSimpleSenseFilter(const struct scsi_sense_disect * sinfo) -{ - if (SCSI_SK_NOT_READY == sinfo->sense_key) - return 1; - else if (SCSI_SK_ILLEGAL_REQUEST == sinfo->sense_key) { - if (SCSI_ASC_UNKNOWN_OPCODE == sinfo->asc) - return 2; - else if (SCSI_ASC_UNKNOWN_FIELD == sinfo->asc) - return 3; - else if (SCSI_ASC_UNKNOWN_PARAM == sinfo->asc) - return 4; - } - return 0; -} - -const char * scsiErrString(int scsiErr) -{ - if (scsiErr < 0) - return strerror(-scsiErr); - switch (scsiErr) { - case 0: - return "no error"; - case 1: - return "device not ready"; - case 2: - return "unsupported scsi opcode"; - case 3: - return "bad value in scsi command"; - case 4: - return "badly formed scsi parameters"; - default: - return "unknown error"; - } -} - -/* Sends LOG SENSE command. Returns 0 if ok, 1 if device NOT READY, 2 if - command not supported, 3 if field (within command) not supported or - returns negated errno. SPC sections 7.6 and 8.2 N.B. Sets PC==1 - to fetch "current cumulative" log pages */ -int scsiLogSense(int device, int pagenum, UINT8 *pBuf, int bufLen) -{ - struct scsi_cmnd_io io_hdr; - struct scsi_sense_disect sinfo; - UINT8 cdb[10]; - UINT8 sense[32]; - int status, res; - - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); - io_hdr.dxfer_dir = DXFER_FROM_DEVICE; - io_hdr.dxfer_len = bufLen; - io_hdr.dxferp = pBuf; - cdb[0] = LOG_SENSE; - cdb[2] = 0x40 | (pagenum & 0x3f); /* Page control (PC)==1 */ - cdb[7] = (bufLen >> 8) & 0xff; - cdb[8] = bufLen & 0xff; - io_hdr.cmnd = cdb; - io_hdr.cmnd_len = sizeof(cdb); - io_hdr.sensep = sense; - io_hdr.max_sense_len = sizeof(sense); - - status = do_scsi_cmnd_io(device, &io_hdr); - scsi_do_sense_disect(&io_hdr, &sinfo); - if ((res = scsiSimpleSenseFilter(&sinfo))) - return res; - if (status > 0) - status = -EIO; - return status; -} - -/* Send MODE SENSE (6 byte) command. Returns 0 if ok, 1 if NOT READY, - * 2 if command not supported (then MODE SENSE(10) should be supported), - * 3 if field in command not supported or returns negated errno. - * SPC sections 7.9 and 8.4 */ -int scsiModeSense(int device, int pagenum, int pc, UINT8 *pBuf, int bufLen) -{ - struct scsi_cmnd_io io_hdr; - struct scsi_sense_disect sinfo; - UINT8 cdb[6]; - UINT8 sense[32]; - int status, res; - - if ((bufLen < 0) || (bufLen > 255)) - return -EINVAL; - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); - io_hdr.dxfer_dir = DXFER_FROM_DEVICE; - io_hdr.dxfer_len = bufLen; - io_hdr.dxferp = pBuf; - cdb[0] = MODE_SENSE; - cdb[2] = (pc << 6) | (pagenum & 0x3f); - cdb[4] = bufLen; - io_hdr.cmnd = cdb; - io_hdr.cmnd_len = sizeof(cdb); - io_hdr.sensep = sense; - io_hdr.max_sense_len = sizeof(sense); - - status = do_scsi_cmnd_io(device, &io_hdr); - scsi_do_sense_disect(&io_hdr, &sinfo); - if ((res = scsiSimpleSenseFilter(&sinfo))) - return res; - if (status > 0) - status = -EIO; - return status; -} - -/* Sends a 6 byte MODE SELECT command. Assumes given pBuf is the response - * from a corresponding 6 byte MODE SENSE command. Such a response should - * have a 4 byte header followed by 0 or more 8 byte block descriptors - * (normally 1) and then 1 mode page. Returns 0 if ok, 1 if NOT READY, - * 2 if command not supported (then MODE SELECT(10) may be supported), - * 3 if field in command not supported, 4 if bad parameter to command - * or returns negated errno. SPC sections 7.7 and 8.4 */ -int scsiModeSelect(int device, int pagenum, int sp, UINT8 *pBuf, int bufLen) -{ - struct scsi_cmnd_io io_hdr; - struct scsi_sense_disect sinfo; - UINT8 cdb[6]; - UINT8 sense[32]; - int status, pg_offset, pg_len, hdr_plus_1_pg, res; - - pg_offset = 4 + pBuf[3]; - if (pg_offset + 2 >= bufLen) - return -EINVAL; - pg_len = pBuf[pg_offset + 1] + 2; - hdr_plus_1_pg = pg_offset + pg_len; - if (hdr_plus_1_pg > bufLen) - return -EINVAL; - pBuf[0] = 0; /* Length of returned mode sense data reserved for SELECT */ - pBuf[pg_offset] &= 0x3f; /* Mask of PS bit from byte 0 of page data */ - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); - io_hdr.dxfer_dir = DXFER_TO_DEVICE; - io_hdr.dxfer_len = hdr_plus_1_pg; - io_hdr.dxferp = pBuf; - cdb[0] = MODE_SELECT; - cdb[1] = 0x10 | (sp & 1); /* set PF (page format) bit always */ - cdb[4] = hdr_plus_1_pg; /* make sure only one page sent */ - io_hdr.cmnd = cdb; - io_hdr.cmnd_len = sizeof(cdb); - io_hdr.sensep = sense; - io_hdr.max_sense_len = sizeof(sense); - - status = do_scsi_cmnd_io(device, &io_hdr); - scsi_do_sense_disect(&io_hdr, &sinfo); - if ((res = scsiSimpleSenseFilter(&sinfo))) - return res; - if (status > 0) - status = -EIO; - return status; -} - -/* MODE SENSE (10 byte). Returns 0 if ok, 1 if NOT READY, 2 if command - * not supported (then MODE SENSE(6) might be supported), 3 if field in - * command not supported or returns negated errno. - * SPC sections 7.10 and 8.4 */ -int scsiModeSense10(int device, int pagenum, int pc, UINT8 *pBuf, int bufLen) -{ - struct scsi_cmnd_io io_hdr; - struct scsi_sense_disect sinfo; - UINT8 cdb[10]; - UINT8 sense[32]; - int status, res; - - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); - io_hdr.dxfer_dir = DXFER_FROM_DEVICE; - io_hdr.dxfer_len = bufLen; - io_hdr.dxferp = pBuf; - cdb[0] = MODE_SENSE_10; - cdb[2] = (pc << 6) | (pagenum & 0x3f); - cdb[7] = (bufLen >> 8) & 0xff; - cdb[8] = bufLen & 0xff; - io_hdr.cmnd = cdb; - io_hdr.cmnd_len = sizeof(cdb); - io_hdr.sensep = sense; - io_hdr.max_sense_len = sizeof(sense); - - status = do_scsi_cmnd_io(device, &io_hdr); - scsi_do_sense_disect(&io_hdr, &sinfo); - if ((res = scsiSimpleSenseFilter(&sinfo))) - return res; - if (status > 0) - status = -EIO; - return status; -} - -/* Sends a 10 byte MODE SELECT command. Assumes given pBuf is the response - * from a corresponding 10 byte MODE SENSE command. Such a response should - * have a 8 byte header followed by 0 or more 8 byte block descriptors - * (normally 1) and then 1 mode page. Returns 0 if ok, 1 NOT REAFY, 2 if - * command not supported (then MODE SELECT(6) may be supported), 3 if field - * in command not supported, 4 if bad parameter to command or returns - * negated errno. SAM sections 7.8 and 8.4 */ -int scsiModeSelect10(int device, int pagenum, int sp, UINT8 *pBuf, int bufLen) -{ - struct scsi_cmnd_io io_hdr; - struct scsi_sense_disect sinfo; - UINT8 cdb[10]; - UINT8 sense[32]; - int status, pg_offset, pg_len, hdr_plus_1_pg, res; - - pg_offset = 8 + (pBuf[6] << 8) + pBuf[7]; - if (pg_offset + 2 >= bufLen) - return -EINVAL; - pg_len = pBuf[pg_offset + 1] + 2; - hdr_plus_1_pg = pg_offset + pg_len; - if (hdr_plus_1_pg > bufLen) - return -EINVAL; - pBuf[0] = 0; - pBuf[1] = 0; /* Length of returned mode sense data reserved for SELECT */ - pBuf[pg_offset] &= 0x3f; /* Mask of PS bit from byte 0 of page data */ - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); - io_hdr.dxfer_dir = DXFER_TO_DEVICE; - io_hdr.dxfer_len = hdr_plus_1_pg; - io_hdr.dxferp = pBuf; - cdb[0] = MODE_SELECT_10; - cdb[1] = 0x10 | (sp & 1); /* set PF (page format) bit always */ - cdb[8] = hdr_plus_1_pg; /* make sure only one page sent */ - io_hdr.cmnd = cdb; - io_hdr.cmnd_len = sizeof(cdb); - io_hdr.sensep = sense; - io_hdr.max_sense_len = sizeof(sense); - - status = do_scsi_cmnd_io(device, &io_hdr); - scsi_do_sense_disect(&io_hdr, &sinfo); - if ((res = scsiSimpleSenseFilter(&sinfo))) - return res; - if (status > 0) - status = -EIO; - return status; -} - -/* Standard INQUIRY returns 0 for ok, anything else is a major problem. - * bufLen should be 36 for unsafe devices (like USB mass storage stuff) - * otherwise they can lock up! SPC sections 7.4 and 8.6 */ -int scsiStdInquiry(int device, UINT8 *pBuf, int bufLen) -{ - struct scsi_cmnd_io io_hdr; - UINT8 cdb[6]; - int status; - - if ((bufLen < 0) || (bufLen > 255)) - return -EINVAL; - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); - io_hdr.dxfer_dir = DXFER_FROM_DEVICE; - io_hdr.dxfer_len = bufLen; - io_hdr.dxferp = pBuf; - cdb[0] = INQUIRY; - cdb[4] = bufLen; - io_hdr.cmnd = cdb; - io_hdr.cmnd_len = sizeof(cdb); - status = do_scsi_cmnd_io(device, &io_hdr); - return status; -} - -/* INQUIRY to fetch Vital Page Data. Returns 0 if ok, 1 if NOT READY - * (unlikely), 2 if command not supported, 3 if field in command not - * supported or returns negated errno. SPC section 7.4 and 8.6 */ -int scsiInquiryVpd(int device, int vpd_page, UINT8 *pBuf, int bufLen) -{ - struct scsi_cmnd_io io_hdr; - struct scsi_sense_disect sinfo; - UINT8 cdb[6]; - UINT8 sense[32]; - int status, res; - - if ((bufLen < 0) || (bufLen > 255)) - return -EINVAL; - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); - io_hdr.dxfer_dir = DXFER_FROM_DEVICE; - io_hdr.dxfer_len = bufLen; - io_hdr.dxferp = pBuf; - cdb[0] = INQUIRY; - cdb[1] = 0x1; /* set EVPD bit (enable Vital Product Data) */ - cdb[2] = vpd_page; - cdb[4] = bufLen; - io_hdr.cmnd = cdb; - io_hdr.cmnd_len = sizeof(cdb); - io_hdr.sensep = sense; - io_hdr.max_sense_len = sizeof(sense); - - status = do_scsi_cmnd_io(device, &io_hdr); - scsi_do_sense_disect(&io_hdr, &sinfo); - if ((res = scsiSimpleSenseFilter(&sinfo))) - return res; - if (status > 0) - status = -EIO; - return status; -} - -/* REQUEST SENSE command. Returns 0 if ok, anything else major problem. - * SPC section 7.24 */ -int scsiRequestSense(int device, struct scsi_sense_disect * sense_info) -{ - struct scsi_cmnd_io io_hdr; - UINT8 cdb[6]; - UINT8 buff[18]; - int status, len; - UINT8 ecode; - - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); - io_hdr.dxfer_dir = DXFER_FROM_DEVICE; - io_hdr.dxfer_len = sizeof(buff); - io_hdr.dxferp = buff; - cdb[0] = REQUEST_SENSE; - cdb[4] = sizeof(buff); - io_hdr.cmnd = cdb; - io_hdr.cmnd_len = sizeof(cdb); - status = do_scsi_cmnd_io(device, &io_hdr); - if ((0 == status) && (sense_info)) { - ecode = buff[0] & 0x7f; - sense_info->error_code = ecode; - sense_info->sense_key = buff[2] & 0xf; - sense_info->asc = 0; - sense_info->ascq = 0; - if ((0x70 == ecode) || (0x71 == ecode)) { - len = buff[7] + 8; - if (len > 13) { - sense_info->asc = buff[12]; - sense_info->ascq = buff[13]; - } - } - } - return status; -} - -/* SEND DIAGNOSTIC command. Returns 0 if ok, 1 if NOT READY, 2 if command - * not supported, 3 if field in command not supported or returns negated - * errno. SPC section 7.25 */ -int scsiSendDiagnostic(int device, int functioncode, UINT8 *pBuf, int bufLen) -{ - struct scsi_cmnd_io io_hdr; - struct scsi_sense_disect sinfo; - UINT8 cdb[6]; - UINT8 sense[32]; - int status, res; - - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); - io_hdr.dxfer_dir = bufLen ? DXFER_TO_DEVICE: DXFER_NONE; - io_hdr.dxfer_len = bufLen; - io_hdr.dxferp = pBuf; - cdb[0] = SEND_DIAGNOSTIC; - if (SCSI_DIAG_DEF_SELF_TEST == functioncode) - cdb[1] = 0x4; /* SelfTest bit */ - else if (SCSI_DIAG_NO_SELF_TEST != functioncode) - cdb[1] = (functioncode & 0x7) << 5; /* SelfTest _code_ */ - else /* SCSI_DIAG_NO_SELF_TEST == functioncode */ - cdb[1] = 0x10; /* PF bit */ - cdb[3] = (bufLen >> 8) & 0xff; - cdb[4] = bufLen & 0xff; - io_hdr.cmnd = cdb; - io_hdr.cmnd_len = sizeof(cdb); - io_hdr.sensep = sense; - io_hdr.max_sense_len = sizeof(sense); - io_hdr.timeout = 5 * 60 * 60; /* five hours because a foreground - extended self tests can take 1 hour plus */ - - status = do_scsi_cmnd_io(device, &io_hdr); - scsi_do_sense_disect(&io_hdr, &sinfo); - if ((res = scsiSimpleSenseFilter(&sinfo))) - return res; - if (status > 0) - status = -EIO; - return status; -} - -/* RECEIVE DIAGNOSTIC command. Returns 0 if ok, 1 if NOT READY, 2 if - * command not supported, 3 if field in command not supported or returns - * negated errno. SPC section 7.17 */ -int scsiReceiveDiagnostic(int device, int pcv, int pagenum, UINT8 *pBuf, - int bufLen) -{ - struct scsi_cmnd_io io_hdr; - struct scsi_sense_disect sinfo; - UINT8 cdb[6]; - UINT8 sense[32]; - int status, res; - - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); - io_hdr.dxfer_dir = DXFER_FROM_DEVICE; - io_hdr.dxfer_len = bufLen; - io_hdr.dxferp = pBuf; - cdb[0] = RECEIVE_DIAGNOSTIC; - cdb[1] = pcv; - cdb[2] = pagenum; - cdb[3] = (bufLen >> 8) & 0xff; - cdb[4] = bufLen & 0xff; - io_hdr.cmnd = cdb; - io_hdr.cmnd_len = sizeof(cdb); - io_hdr.sensep = sense; - io_hdr.max_sense_len = sizeof(sense); - - status = do_scsi_cmnd_io(device, &io_hdr); - scsi_do_sense_disect(&io_hdr, &sinfo); - if ((res = scsiSimpleSenseFilter(&sinfo))) - return res; - if (status > 0) - status = -EIO; - return status; -} - -/* TEST UNIT READY command. SPC section 7.28 (probably in SBC as well) */ -static int _testunitready(int device, struct scsi_sense_disect * sinfo) -{ - struct scsi_cmnd_io io_hdr; - UINT8 cdb[6]; - UINT8 sense[32]; - int status; - - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); - io_hdr.dxfer_dir = DXFER_NONE; - io_hdr.dxfer_len = 0; - io_hdr.dxferp = NULL; - cdb[0] = TEST_UNIT_READY; - io_hdr.cmnd = cdb; - io_hdr.cmnd_len = sizeof(cdb); - io_hdr.sensep = sense; - io_hdr.max_sense_len = sizeof(sense); - - status = do_scsi_cmnd_io(device, &io_hdr); - scsi_do_sense_disect(&io_hdr, sinfo); - return status; -} - -/* Returns 0 for device responds and media ready, 1 for device responds and - media not ready, or returns a negated errno value */ -int scsiTestUnitReady(int device) -{ - struct scsi_sense_disect sinfo; - int status; - - status = _testunitready(device, &sinfo); - if (SCSI_SK_NOT_READY == sinfo.sense_key) - return 1; - else if (SCSI_SK_UNIT_ATTENTION == sinfo.sense_key) { - /* power on reset, media changed, ok ... try again */ - status = _testunitready(device, &sinfo); - if (SCSI_SK_NOT_READY == sinfo.sense_key) - return 1; - } - return status; -} - -/* Offset into mode sense (6 or 10 byte) response that actual mode page - * starts at (relative to resp[0]). Returns -1 if problem */ -static int scsiModePageOffset(const UINT8 * resp, int len, int modese_10) -{ - int resp_len, bd_len; - int offset = -1; - - if (resp) { - if (modese_10) { - resp_len = (resp[0] << 8) + resp[1] + 2; - bd_len = (resp[6] << 8) + resp[7]; - offset = bd_len + 8; - } else { - resp_len = resp[0] + 1; - bd_len = resp[3]; - offset = bd_len + 4; - } - if ((offset + 2) > len) { - pout("scsiModePageOffset: raw_curr too small, offset=%d " - "resp_len=%d bd_len=%d\n", offset, resp_len, bd_len); - offset = -1; - } else if ((offset + 2) > resp_len) { - pout("scsiModePageOffset: bad resp_len=%d offset=%d bd_len=%d\n", - resp_len, offset, bd_len); - offset = -1; - } - } - return offset; -} - -/* IEC mode page byte 2 bit masks */ -#define DEXCPT_ENABLE 0x08 -#define EWASC_ENABLE 0x10 -#define DEXCPT_DISABLE 0xf7 -#define EWASC_DISABLE 0xef -#define TEST_DISABLE 0xfb - -int scsiFetchIECmpage(int device, struct scsi_iec_mode_page *iecp) -{ - int err; - - memset(iecp, 0, sizeof(*iecp)); - iecp->requestedCurrent = 1; - if ((err = scsiModeSense(device, INFORMATIONAL_EXCEPTIONS_CONTROL, - 0, iecp->raw_curr, sizeof(iecp->raw_curr)))) { - if (2 == err) { /* opcode no good so try 10 byte mode sense */ - err = scsiModeSense10(device, INFORMATIONAL_EXCEPTIONS_CONTROL, - 0, iecp->raw_curr, sizeof(iecp->raw_curr)); - if (0 == err) - iecp->modese_10 = 1; - else - return err; - } else - return err; - } - iecp->gotCurrent = 1; - iecp->requestedChangeable = 1; - if (iecp->modese_10) { - if (0 == scsiModeSense10(device, INFORMATIONAL_EXCEPTIONS_CONTROL, - 1, iecp->raw_chg, sizeof(iecp->raw_chg))) - iecp->gotChangeable = 1; - } else { - if (0 == scsiModeSense(device, INFORMATIONAL_EXCEPTIONS_CONTROL, - 1, iecp->raw_chg, sizeof(iecp->raw_chg))) - iecp->gotChangeable = 1; - } - return 0; -} - -/* Return 0 if ok, -EINVAL if problems */ -int scsiDecodeIEModePage(const struct scsi_iec_mode_page *iecp, - UINT8 *byte_2p, UINT8 *mrie_p, unsigned int *interval_timer_p, - unsigned int *report_count_p) -{ - int offset, len; - - if (iecp && iecp->gotCurrent) { - offset = scsiModePageOffset(iecp->raw_curr, sizeof(iecp->raw_curr), - iecp->modese_10); - if (offset >= 0) { - len = iecp->raw_curr[offset + 1] + 2; - if (byte_2p) - *byte_2p = iecp->raw_curr[offset + 2]; - if (mrie_p) - *mrie_p = iecp->raw_curr[offset + 3] & 0xf; - if (interval_timer_p && (len > 7)) - *interval_timer_p = (iecp->raw_curr[offset + 4] << 24) + - (iecp->raw_curr[offset + 5] << 16) + - (iecp->raw_curr[offset + 6] << 8) + - iecp->raw_curr[offset + 7]; - else if (interval_timer_p) - *interval_timer_p = 0; - if (report_count_p && (len > 11)) - *report_count_p = (iecp->raw_curr[offset + 8] << 24) + - (iecp->raw_curr[offset + 9] << 16) + - (iecp->raw_curr[offset + 10] << 8) + - iecp->raw_curr[offset + 11]; - else if (report_count_p) - *report_count_p = 0; - return 0; - } else - return -EINVAL; - } else - return -EINVAL; -} - -int scsi_IsExceptionControlEnabled(const struct scsi_iec_mode_page *iecp) -{ - int offset; - - if (iecp && iecp->gotCurrent) { - offset = scsiModePageOffset(iecp->raw_curr, sizeof(iecp->raw_curr), - iecp->modese_10); - if (offset >= 0) - return (iecp->raw_curr[offset + 2] & DEXCPT_ENABLE) ? 0 : 1; - else - return 0; - } else - return 0; -} - -int scsi_IsWarningEnabled(const struct scsi_iec_mode_page *iecp) -{ - int offset; - - if (iecp && iecp->gotCurrent) { - offset = scsiModePageOffset(iecp->raw_curr, sizeof(iecp->raw_curr), - iecp->modese_10); - if (offset >= 0) - return (iecp->raw_curr[offset + 2] & EWASC_ENABLE) ? 1 : 0; - else - return 0; - } else - return 0; -} - -/* set EWASC and clear PERF, EBF, DEXCPT TEST and LOGERR */ -#define SCSI_IEC_MP_BYTE2_ENABLED 0x10 -#define SCSI_IEC_MP_BYTE2_TEST_MASK 0x4 -/* exception/warning via an unrequested REQUEST SENSE command */ -#define SCSI_IEC_MP_MRIE 6 -#define SCSI_IEC_MP_INTERVAL_T 0 -#define SCSI_IEC_MP_REPORT_COUNT 1 - -/* Try to set (or clear) both Exception Control and Warning in the IE - * mode page subject to the "changeable" mask. The object pointed to - * by iecp is (possibly) inaccurate after this call, therefore - * scsiFetchIECmpage() should be called again if the IEC mode page - * is to be re-examined. - * When -r ioctl is invoked 3 or more time on 'smartctl -s on ...' - * then set the TEST bit (causes asc,ascq pair of 0x5d,0xff). */ -int scsiSetExceptionControlAndWarning(int device, int enabled, - const struct scsi_iec_mode_page *iecp) -{ - int k, offset, err; - UINT8 rout[SCSI_IECMP_RAW_LEN]; - int sp, eCEnabled, wEnabled; - - if ((! iecp) || (! iecp->gotCurrent)) - return -EINVAL; - offset = scsiModePageOffset(iecp->raw_curr, sizeof(iecp->raw_curr), - iecp->modese_10); - if (offset < 0) - return -EINVAL; - memcpy(rout, iecp->raw_curr, SCSI_IECMP_RAW_LEN); - rout[0] = 0; /* Mode Data Length reserved in MODE SELECTs */ - if (iecp->modese_10) - rout[1] = 0; - sp = (rout[offset] & 0x80) ? 1 : 0; /* PS bit becomes 'SELECT's SP bit */ - rout[offset] &= 0x7f; /* mask off PS bit */ - if (enabled) { - rout[offset + 2] = SCSI_IEC_MP_BYTE2_ENABLED; - if (con->reportscsiioctl > 2) - rout[offset + 2] |= SCSI_IEC_MP_BYTE2_TEST_MASK; - rout[offset + 3] = SCSI_IEC_MP_MRIE; - rout[offset + 4] = (SCSI_IEC_MP_INTERVAL_T >> 24) & 0xff; - rout[offset + 5] = (SCSI_IEC_MP_INTERVAL_T >> 16) & 0xff; - rout[offset + 6] = (SCSI_IEC_MP_INTERVAL_T >> 8) & 0xff; - rout[offset + 7] = SCSI_IEC_MP_INTERVAL_T & 0xff; - rout[offset + 8] = (SCSI_IEC_MP_REPORT_COUNT >> 24) & 0xff; - rout[offset + 9] = (SCSI_IEC_MP_REPORT_COUNT >> 16) & 0xff; - rout[offset + 10] = (SCSI_IEC_MP_REPORT_COUNT >> 8) & 0xff; - rout[offset + 11] = SCSI_IEC_MP_REPORT_COUNT & 0xff; - if (iecp->gotChangeable) { - UINT8 chg2 = iecp->raw_chg[offset + 2]; - - rout[offset + 2] = chg2 ? (rout[offset + 2] & chg2) : - iecp->raw_curr[offset + 2]; - for (k = 3; k < 12; ++k) { - if (0 == iecp->raw_chg[offset + k]) - rout[offset + k] = iecp->raw_curr[offset + k]; - } - } - if (0 == memcmp(&rout[offset + 2], &iecp->raw_chg[offset + 2], 10)) { - if (con->reportscsiioctl > 0) - pout("scsiSetExceptionControlAndWarning: already enabled\n"); - return 0; - } - } else { /* disabling Exception Control and (temperature) Warnings */ - eCEnabled = (rout[offset + 2] & DEXCPT_ENABLE) ? 0 : 1; - wEnabled = (rout[offset + 2] & EWASC_ENABLE) ? 1 : 0; - if ((! eCEnabled) && (! wEnabled)) { - if (con->reportscsiioctl > 0) - pout("scsiSetExceptionControlAndWarning: already disabled\n"); - return 0; /* nothing to do, leave other setting alone */ - } - if (wEnabled) - rout[offset + 2] &= EWASC_DISABLE; - if (eCEnabled) { - if (iecp->gotChangeable && - (iecp->raw_chg[offset + 2] & DEXCPT_ENABLE)) - rout[offset + 2] |= DEXCPT_ENABLE; - rout[offset + 2] &= TEST_DISABLE;/* clear TEST bit for spec */ - } - } - if (iecp->modese_10) - err = scsiModeSelect10(device, INFORMATIONAL_EXCEPTIONS_CONTROL, - sp, rout, sizeof(rout)); - else - err = scsiModeSelect(device, INFORMATIONAL_EXCEPTIONS_CONTROL, - sp, rout, sizeof(rout)); - return err; -} - -int scsiGetTemp(int device, UINT8 *currenttemp, UINT8 *triptemp) -{ - UINT8 tBuf[252]; - int err; - - if ((err = scsiLogSense(device, TEMPERATURE_PAGE, tBuf, sizeof(tBuf)))) { - *currenttemp = 0; - *triptemp = 0; - pout("Log Sense for temperature failed [%s]\n", scsiErrString(err)); - return 1; - } - *currenttemp = tBuf[9]; - *triptemp = tBuf[15]; - return 0; -} - -/* Read informational exception log page or Request Sense response. - * Fetching asc/ascq code potentially flagging an exception or warning. - * Returns 0 if ok, else error number. A current temperature of 255 - * (Centigrade) if for temperature not available. */ -int scsiCheckIE(int device, int method, int hasTempLogPage, - UINT8 *asc, UINT8 *ascq, UINT8 *currenttemp) -{ - UINT8 tBuf[252]; - struct scsi_sense_disect sense_info; - int err; - int temperatureSet = 0; - unsigned short pagesize; - UINT8 currTemp, tripTemp; - - *asc = 0; - *ascq = 0; - *currenttemp = 0; - memset(&sense_info, 0, sizeof(sense_info)); - if (method == CHECK_SMART_BY_LGPG_2F) { - if ((err = scsiLogSense(device, IE_LOG_PAGE, tBuf, sizeof(tBuf)))) { - pout("Log Sense failed, IE page [%s]\n", scsiErrString(err)); - return 5; - } - pagesize = (unsigned short) (tBuf[2] << 8) | tBuf[3]; - if ((pagesize < 4) || tBuf[4] || tBuf[5]) { - pout("Log Sense failed, IE page, bad parameter code or length\n"); - return 5; - } - if (tBuf[7] > 1) { - sense_info.asc = tBuf[8]; - sense_info.ascq = tBuf[9]; - if (tBuf[7] > 2) { - *currenttemp = tBuf[10]; - temperatureSet = 1; - } - } - } - if (0 == sense_info.asc) { - /* ties in with MRIE field of 6 in IEC mode page (0x1c) */ - if ((err = scsiRequestSense(device, &sense_info))) { - pout("Request Sense failed, [%s]\n", scsiErrString(err)); - return 5; - } - } - *asc = sense_info.asc; - *ascq = sense_info.ascq; - if ((! temperatureSet) && hasTempLogPage) { - if (0 == scsiGetTemp(device, &currTemp, &tripTemp)) - *currenttemp = currTemp; - } - return 0; -} - -static const char * TapeAlertsMessageTable[]= { - " ", - "The tape drive is having problems reading data. No data has been lost, " - "but there has been a reduction in the performance of the tape.", - "The tape drive is having problems writing data. No data has been lost, " - "but there has been a reduction in the performance of the tape.", - "The operation has stopped because an error has occurred while reading " - "or writing data which the drive cannot correct.", - "Your data is at risk:\n1. Copy any data you require from this tape. \n" - "2. Do not use this tape again.\n" - "3. Restart the operation with a different tape.", - "The tape is damaged or the drive is faulty. Call the tape drive " - "supplier helpline.", - "The tape is from a faulty batch or the tape drive is faulty:\n" - "1. Use a good tape to test the drive.\n" - "2. If problem persists, call the tape drive supplier helpline.", - "The tape cartridge has reached the end of its calculated useful life: \n" - "1. Copy data you need to another tape.\n" - "2. Discard the old tape.", - "The tape cartridge is not data-grade. Any data you back up to the tape " - "is at risk. Replace the cartridge with a data-grade tape.", - "You are trying to write to a write-protected cartridge. Remove the " - "write-protection or use another tape.", - "You cannot eject the cartridge because the tape drive is in use. Wait " - "until the operation is complete before ejecting the cartridge.", - "The tape in the drive is a cleaning cartridge.", - "You have tried to load a cartridge of a type which is not supported " - "by this drive.", - "The operation has failed because the tape in the drive has snapped:\n" - "1. Discard the old tape.\n" - "2. Restart the operation with a different tape.", - "The operation has failed because the tape in the drive has snapped:\n" - "1. Do not attempt to extract the tape cartridge\n" - "2. Call the tape drive supplier helpline.", - "The memory in the tape cartridge has failed, which reduces performance. " - "Do not use the cartridge for further backup operations.", - "The operation has failed because the tape cartridge was manually " - "ejected while the tape drive was actively writing or reading.", - "You have loaded of a type that is read-only in this drive. The " - "cartridge will appear as write-protected.", - "The directory on the tape cartridge has been corrupted. File search " - "performance will be degraded. The tape directory can be rebuilt " - "by reading all the data on the cartridge.", - "The tape cartridge is nearing the end of its calculated life. It is " - "recommended that you:\n" - "1. Use another tape cartridge for your next backup.\n" - "2. Store this tape in a safe place in case you need to restore " - "data from it.", - "The tape drive needs cleaning:\n" - "1. If the operation has stopped, eject the tape and clean the drive.\n" - "2. If the operation has not stopped, wait for it to finish and then " - "clean the drive. Check the tape drive users manual for device " - "specific cleaning instructions.", - "The tape drive is due for routine cleaning:\n" - "1. Wait for the current operation to finish.\n" - "2. The use a cleaning cartridge. Check the tape drive users manual " - "for device specific cleaning instructions.", - "The last cleaning cartridge used in the tape drive has worn out:\n" - "1. Discard the worn out cleaning cartridge.\n" - "2. Wait for the current operation to finish.\n" - "3. Then use a new cleaning cartridge.", - "The last cleaning cartridge used in the tape drive was an invalid type:\n" - "1. Do not use this cleaning cartridge in this drive.\n" - "2. Wait for the current operation to finish.\n" - "3. Then use a new cleaning cartridge.", - "The tape drive has requested a retention operation", - "A redundant interface port on the tape drive has failed", - "A tape drive cooling fan has failed", - "A redundant power supply has failed inside the tape drive enclosure. " - "Check the enclosure users manual for instructions on replacing the " - "failed power supply.", - "The tape drive power consumption is outside the specified range.", - "Preventive maintenance of the tape drive is required. Check the tape " - "drive users manual for device specific preventive maintenance " - "tasks or call the tape drive supplier helpline.", - "The tape drive has a hardware fault:\n" - "1. Eject the tape or magazine.\n" - "2. Reset the drive.\n" - "3. Restart the operation.", - "The tape drive has a hardware fault:\n" - "1. Turn the tape drive off and then on again.\n" - "2. Restart the operation.\n" - "3. If the problem persists, call the tape drive supplier helpline.\n" - " Check the tape drive users manual for device specific instructions " - "on turning the device power in and off.", - "The tape drive has a problem with the host interface:\n" - "1. Check the cables and cable connections.\n" - "2. Restart the operation.", - "The operation has failed:\n" - "1. Eject the tape or magazine.\n" - "2. Insert the tape or magazine again.\n" - "3. Restart the operation.", - "The firmware download has failed because you have tried to use the " - "incorrect firmware for this tape drive. Obtain the correct " - "firmware and try again.", - "Environmental conditions inside the tape drive are outside the " - "specified humidity range.", - "Environmental conditions inside the tape drive are outside the " - "specified temperature range.", - "The voltage supply to the tape drive is outside the specified range.", - "A hardware failure of the tape drive is predicted. Call the tape " - "drive supplier helpline.", - "The tape drive may have a fault. Check for availability of diagnostic " - "information and run extended diagnostics if applicable. Check the " - "tape drive users manual for instruction on running extended " - "diagnostic tests and retrieving diagnostic data", - "The changer mechanism is having difficulty communicating with the tape " - "drive:\n" - "1. Turn the autoloader off then on.\n" - "2. Restart the operation.\n" - "3. If problem persists, call the tape drive supplier helpline.", - "A tape has been left in the autoloader by a previous hardware fault:\n" - "1. Insert an empty magazine to clear the fault.\n" - "2. If the fault does not clear, turn the autoloader off and then " - "on again.\n" - "3. If the problem persists, call the tape drive supplier helpline.", - "There is a problem with the autoloader mechanism.", - "The operation has failed because the autoloader door is open:\n" - "1. Clear any obstructions from the autoloader door.\n" - "2. Eject the magazine and then insert it again.\n" - "3. If the fault does not clear, turn the autoloader off and then " - "on again.\n" - "4. If the problem persists, call the tape drive supplier helpline.", - "The autoloader has a hardware fault:\n" - "1. Turn the autoloader off and then on again.\n" - "2. Restart the operation.\n" - "3. If the problem persists, call the tape drive supplier helpline.\n" - " Check the autoloader users manual for device specific instructions " - "on turning the device power on and off.", - "The autoloader cannot operate without the magazine,\n" - "1. Insert the magazine into the autoloader.\n" - "2. Restart the operation.", - "A hardware failure of the changer mechanism is predicted. Call the " - "tape drive supplier helpline.", - " ", - " ", - " ", - "Media statistics have been lost at some time in the past", - "The tape directory on the tape cartridge just unloaded has been " - "corrupted. File search performance will be degraded. The tape " - "directory can be rebuilt by reading all the data.", - "The tape just unloaded could not write its system area successfully:\n" - "1. Copy data to another tape cartridge.\n" - "2. Discard the old cartridge.", - "The tape system are could not be read successfully at load time:\n" - "1. Copy data to another tape cartridge.\n" - "2. Discard the old cartridge.", - "The start or data could not be found on the tape:\n" - "1. Check you are using the correct format tape.\n" - "2. Discard the tape or return the tape to you supplier", - }; - -const char * scsiTapeAlertsTapeDevice(unsigned short code) -{ - const int num = sizeof(TapeAlertsMessageTable) / - sizeof(TapeAlertsMessageTable[0]); - - return (code < num) ? TapeAlertsMessageTable[code] : "Unknown Alert"; -} - -static const char * ChangerTapeAlertsMessageTable[]= { - " ", - "The library mechanism is having difficulty communicating with the drive:\n" - "1. Turn the library off then on.\n" - "2. Restart the operation.\n" - "3. If the problem persists, call the library supplier help line.", - "There is a problem with the library mechanism. If problem persists,\n" - "call the library supplier help line.", - "The library has a hardware fault:\n" - "1. Reset the library.\n" - "2. Restart the operation.\n" - "Check the library users manual for device specific instructions on resetting\n" - "the device.", - "The library has a hardware fault:\n" - "1. Turn the library off then on again.\n" - "2. Restart the operation.\n" - "3. If the problem persists, call the library supplier help line.\n" - "Check the library users manual for device specific instructions on turning the\n" - "device power on and off.", - "The library mechanism may have a hardware fault.\n" - "Run extended diagnostics to verify and diagnose the problem. Check the library\n" - "users manual for device specific instructions on running extended diagnostic\n" - "tests.", - "The library has a problem with the host interface:\n" - "1. Check the cables and connections.\n" - "2. Restart the operation.", - "A hardware failure of the library is predicted. Call the library\n" - "supplier help line.", - "Preventive maintenance of the library is required.\n" - "Check the library users manual for device specific preventative maintenance\n" - "tasks, or call your library supplier help line.", - "General environmental conditions inside the library are outside the\n" - "specified humidity range.", - "General environmental conditions inside the library are outside the\n" - "specified temperature range.", - "The voltage supply to the library is outside the specified range.\n" - "There is a potential problem with the power supply or failure of\n" - "a redundant power supply.", - "A cartridge has been left inside the library by a previous hardware\n" - "fault:\n" - "1. Insert an empty magazine to clear the fault.\n" - "2. If the fault does not clear, turn the library off and then on again.\n" - "3. If the problem persists, call the library supplier help line.", - "There is a potential problem with the drive ejecting cartridges or with\n" - "the library mechanism picking a cartridge from a slot.\n" - "1. No action needs to be taken at this time.\n" - "2. If the problem persists, call the library supplier help line.", - "There is a potential problem with the library mechanism placing a cartridge\n" - "into a slot.\n" - "1. No action needs to be taken at this time.\n" - "2. If the problem persists, call the library supplier help line.", - "There is a potential problem with the drive or the library mechanism\n" - "loading cartridges, or an incompatible cartridge.", - "The library has failed because the door is open:\n" - "1. Clear any obstructions from the library door.\n" - "2. Close the library door.\n" - "3. If the problem persists, call the library supplier help line.", - "There is a mechanical problem with the library media import/export\n" - "mailslot.", - "The library cannot operate without the magazine.\n" - "1. Insert the magazine into the library.\n" - "2. Restart the operation.", - "Library security has been compromised.", - "The library security mode has been changed.\n" - "The library has either been put into secure mode, or the library has exited\n" - "the secure mode.\n" - "This is for information purposes only. No action is required.", - "The library has been manually turned offline and is unavailable for use.", - "A drive inside the library has been taken offline.\n" - "This is for information purposes only. No action is required.", - "There is a potential problem with the bar code label or the scanner\n" - "hardware in the library mechanism.\n" - "1. No action needs to be taken at this time.\n" - "2. If the problem persists, call the library supplier help line.", - "The library has detected an inconsistency in its inventory.\n" - "1. Redo the library inventory to correct inconsistency.\n" - "2. Restart the operation.\n" - "Check the applications users manual or the hardware users manual for\n" - "specific instructions on redoing the library inventory.", - "A library operation has been attempted that is invalid at this time.", - "A redundant interface port on the library has failed.", - "A library cooling fan has failed.", - "A redundant power supply has failed inside the library. Check the\n" - "library users manual for instructions on replacing the failed power supply.", - "The library power consumption is outside the specified range.", - "A failure has occurred in the cartridge pass-through mechanism between\n" - "two library modules.", - "A cartridge has been left in the pass-through mechanism from a previous\n" - "hardware fault. Check the library users guide for instructions on clearing\n" - "this fault.", - "The library was unable to read the bar code on a cartridge.", -}; - -const char * scsiTapeAlertsChangerDevice(unsigned short code) -{ - const int num = sizeof(ChangerTapeAlertsMessageTable) / - sizeof(ChangerTapeAlertsMessageTable[0]); - - return (code < num) ? ChangerTapeAlertsMessageTable[code] : "Unknown Alert"; -} - - -/* this is a subset of the SCSI additional sense code strings indexed - * by "ascq" for the case when asc==SCSI_ASC_IMPENDING_FAILURE (0x5d) - */ -static const char * strs_for_asc_5d[] = { - /* 0x00 */ "FAILURE PREDICTION THRESHOLD EXCEEDED", - "MEDIA FAILURE PREDICTION THRESHOLD EXCEEDED", - "LOGICAL UNIT FAILURE PREDICTION THRESHOLD EXCEEDED", - "SPARE AREA EXHAUSTION PREDICTION THRESHOLD EXCEEDED", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - /* 0x10 */ "HARDWARE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE", - "HARDWARE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH", - "HARDWARE IMPENDING FAILURE DATA ERROR RATE TOO HIGH", - "HARDWARE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH", - "HARDWARE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS", - "HARDWARE IMPENDING FAILURE ACCESS TIMES TOO HIGH", - "HARDWARE IMPENDING FAILURE START UNIT TIMES TOO HIGH", - "HARDWARE IMPENDING FAILURE CHANNEL PARAMETRICS", - "HARDWARE IMPENDING FAILURE CONTROLLER DETECTED", - "HARDWARE IMPENDING FAILURE THROUGHPUT PERFORMANCE", - "HARDWARE IMPENDING FAILURE SEEK TIME PERFORMANCE", - "HARDWARE IMPENDING FAILURE SPIN-UP RETRY COUNT", - "HARDWARE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT", - "", - "", - "", - /* 0x20 */ "CONTROLLER IMPENDING FAILURE GENERAL HARD DRIVE FAILURE", - "CONTROLLER IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH", - "CONTROLLER IMPENDING FAILURE DATA ERROR RATE TOO HIGH", - "CONTROLLER IMPENDING FAILURE SEEK ERROR RATE TOO HIGH", - "CONTROLLER IMPENDING FAILURE TOO MANY BLOCK REASSIGNS", - "CONTROLLER IMPENDING FAILURE ACCESS TIMES TOO HIGH", - "CONTROLLER IMPENDING FAILURE START UNIT TIMES TOO HIGH", - "CONTROLLER IMPENDING FAILURE CHANNEL PARAMETRICS", - "CONTROLLER IMPENDING FAILURE CONTROLLER DETECTED", - "CONTROLLER IMPENDING FAILURE THROUGHPUT PERFORMANCE", - "CONTROLLER IMPENDING FAILURE SEEK TIME PERFORMANCE", - "CONTROLLER IMPENDING FAILURE SPIN-UP RETRY COUNT", - "CONTROLLER IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT", - "", - "", - "", - /* 0x30 */ "DATA CHANNEL IMPENDING FAILURE GENERAL HARD DRIVE FAILURE", - "DATA CHANNEL IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH", - "DATA CHANNEL IMPENDING FAILURE DATA ERROR RATE TOO HIGH", - "DATA CHANNEL IMPENDING FAILURE SEEK ERROR RATE TOO HIGH", - "DATA CHANNEL IMPENDING FAILURE TOO MANY BLOCK REASSIGNS", - "DATA CHANNEL IMPENDING FAILURE ACCESS TIMES TOO HIGH", - "DATA CHANNEL IMPENDING FAILURE START UNIT TIMES TOO HIGH", - "DATA CHANNEL IMPENDING FAILURE CHANNEL PARAMETRICS", - "DATA CHANNEL IMPENDING FAILURE CONTROLLER DETECTED", - "DATA CHANNEL IMPENDING FAILURE THROUGHPUT PERFORMANCE", - "DATA CHANNEL IMPENDING FAILURE SEEK TIME PERFORMANCE", - "DATA CHANNEL IMPENDING FAILURE SPIN-UP RETRY COUNT", - "DATA CHANNEL IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT", - "", - "", - "", - /* 0x40 */ "SERVO IMPENDING FAILURE GENERAL HARD DRIVE FAILURE", - "SERVO IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH", - "SERVO IMPENDING FAILURE DATA ERROR RATE TOO HIGH", - "SERVO IMPENDING FAILURE SEEK ERROR RATE TOO HIGH", - "SERVO IMPENDING FAILURE TOO MANY BLOCK REASSIGNS", - "SERVO IMPENDING FAILURE ACCESS TIMES TOO HIGH", - "SERVO IMPENDING FAILURE START UNIT TIMES TOO HIGH", - "SERVO IMPENDING FAILURE CHANNEL PARAMETRICS", - "SERVO IMPENDING FAILURE CONTROLLER DETECTED", - "SERVO IMPENDING FAILURE THROUGHPUT PERFORMANCE", - "SERVO IMPENDING FAILURE SEEK TIME PERFORMANCE", - "SERVO IMPENDING FAILURE SPIN-UP RETRY COUNT", - "SERVO IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT", - "", - "", - "", - /* 0x50 */ "SPINDLE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE", - "SPINDLE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH", - "SPINDLE IMPENDING FAILURE DATA ERROR RATE TOO HIGH", - "SPINDLE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH", - "SPINDLE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS", - "SPINDLE IMPENDING FAILURE ACCESS TIMES TOO HIGH", - "SPINDLE IMPENDING FAILURE START UNIT TIMES TOO HIGH", - "SPINDLE IMPENDING FAILURE CHANNEL PARAMETRICS", - "SPINDLE IMPENDING FAILURE CONTROLLER DETECTED", - "SPINDLE IMPENDING FAILURE THROUGHPUT PERFORMANCE", - "SPINDLE IMPENDING FAILURE SEEK TIME PERFORMANCE", - "SPINDLE IMPENDING FAILURE SPIN-UP RETRY COUNT", - "SPINDLE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT", - "", - "", - "", - /* 0x60 */ "FIRMWARE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE", - "FIRMWARE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH", - "FIRMWARE IMPENDING FAILURE DATA ERROR RATE TOO HIGH", - "FIRMWARE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH", - "FIRMWARE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS", - "FIRMWARE IMPENDING FAILURE ACCESS TIMES TOO HIGH", - "FIRMWARE IMPENDING FAILURE START UNIT TIMES TOO HIGH", - "FIRMWARE IMPENDING FAILURE CHANNEL PARAMETRICS", - "FIRMWARE IMPENDING FAILURE CONTROLLER DETECTED", - "FIRMWARE IMPENDING FAILURE THROUGHPUT PERFORMANCE", - "FIRMWARE IMPENDING FAILURE SEEK TIME PERFORMANCE", - "FIRMWARE IMPENDING FAILURE SPIN-UP RETRY COUNT", - /* 0x6c */ "FIRMWARE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"}; - - -/* this is a subset of the SCSI additional sense code strings indexed - * * by "ascq" for the case when asc==SCSI_ASC_WARNING (0xb) - * */ -static const char * strs_for_asc_b[] = { - /* 0x00 */ "WARNING", - "WARNING - SPECIFIED TEMPERATURE EXCEEDED", - "WARNING - ENCLOSURE DEGRADED"}; - -static char spare_buff[128]; - -const char * scsiGetIEString(UINT8 asc, UINT8 ascq) -{ - const char * rp; - - if (SCSI_ASC_IMPENDING_FAILURE == asc) { - if (ascq == 0xff) - return "FAILURE PREDICTION THRESHOLD EXCEEDED (FALSE)"; - else if (ascq < - (sizeof(strs_for_asc_5d) / sizeof(strs_for_asc_5d[0]))) { - rp = strs_for_asc_5d[ascq]; - if (strlen(rp) > 0) - return rp; - } - snprintf(spare_buff, sizeof(spare_buff), - "FAILURE PREDICTION THRESHOLD EXCEEDED: ascq=0x%x", ascq); - return spare_buff; - } else if (SCSI_ASC_WARNING == asc) { - if (ascq < (sizeof(strs_for_asc_b) / sizeof(strs_for_asc_b[0]))) { - rp = strs_for_asc_b[ascq]; - if (strlen(rp) > 0) - return rp; - } - snprintf(spare_buff, sizeof(spare_buff), "WARNING: ascq=0x%x", ascq); - return spare_buff; - } - return NULL; /* not a IE additional sense code */ -} - - -/* This is not documented in t10.org, page 0x80 is vendor specific */ -/* Some IBM disks do an offline read-scan when they get this command. */ -int scsiSmartIBMOfflineTest(int device) -{ - UINT8 tBuf[256]; - - memset(tBuf, 0, sizeof(tBuf)); - /* Build SMART Off-line Immediate Diag Header */ - tBuf[0] = 0x80; /* Page Code */ - tBuf[1] = 0x00; /* Reserved */ - tBuf[2] = 0x00; /* Page Length MSB */ - tBuf[3] = 0x04; /* Page Length LSB */ - tBuf[4] = 0x03; /* SMART Revision */ - tBuf[5] = 0x00; /* Reserved */ - tBuf[6] = 0x00; /* Off-line Immediate Time MSB */ - tBuf[7] = 0x00; /* Off-line Immediate Time LSB */ - return scsiSendDiagnostic(device, SCSI_DIAG_NO_SELF_TEST, tBuf, 8); -} - -int scsiSmartDefaultSelfTest(int device) -{ - return scsiSendDiagnostic(device, SCSI_DIAG_DEF_SELF_TEST, NULL, 0); -} - -int scsiSmartShortSelfTest(int device) -{ - return scsiSendDiagnostic(device, SCSI_DIAG_BG_SHORT_SELF_TEST, NULL, 0); -} - -int scsiSmartExtendSelfTest(int device) -{ - return scsiSendDiagnostic(device, SCSI_DIAG_BG_EXTENDED_SELF_TEST, - NULL, 0); -} - -int scsiSmartShortCapSelfTest(int device) -{ - return scsiSendDiagnostic(device, SCSI_DIAG_FG_SHORT_SELF_TEST, NULL, 0); -} - -int scsiSmartExtendCapSelfTest(int device) -{ - return scsiSendDiagnostic(device, SCSI_DIAG_FG_EXTENDED_SELF_TEST, - NULL, 0); -} - -int scsiSmartSelfTestAbort(int device) -{ - return scsiSendDiagnostic(device, SCSI_DIAG_ABORT_SELF_TEST, NULL, 0); -} - -int scsiFetchExtendedSelfTestTime(int device, int * durationSec) -{ - int err, offset, res; - UINT8 buff[64]; - int modese_10 = 0; - - memset(buff, 0, sizeof(buff)); - if ((err = scsiModeSense(device, CONTROL_MODE_PAGE_PARAMETERS, - 0, buff, sizeof(buff)))) { - if (2 == err) { /* opcode no good so try 10 byte mode sense */ - err = scsiModeSense10(device, CONTROL_MODE_PAGE_PARAMETERS, - 0, buff, sizeof(buff)); - if (0 == err) - modese_10 = 1; - else - return err; - } else - return err; - } - offset = scsiModePageOffset(buff, sizeof(buff), modese_10); - if (offset < 0) - return -EINVAL; - if (buff[offset + 1] >= 0xa) { - res = (buff[offset + 10] << 8) | buff[offset + 11]; - *durationSec = res; - return 0; - } - else - return -EINVAL; -} - -void scsiDecodeErrCounterPage(unsigned char * resp, - struct scsiErrorCounter *ecp) -{ - int k, j, num, pl, pc; - unsigned char * ucp; - unsigned char * xp; - unsigned long long * ullp; - - memset(ecp, 0, sizeof(*ecp)); - num = (resp[2] << 8) | resp[3]; - ucp = &resp[0] + 4; - while (num > 3) { - pc = (ucp[0] << 8) | ucp[1]; - pl = ucp[3] + 4; - switch (pc) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - ecp->gotPC[pc] = 1; - ullp = &ecp->counter[pc]; - break; - default: - ecp->gotExtraPC = 1; - ullp = &ecp->counter[7]; - break; - } - k = pl - 4; - xp = ucp + 4; - if (k > sizeof(*ullp)) { - xp += (k - sizeof(*ullp)); - k = sizeof(*ullp); - } - *ullp = 0; - for (j = 0; j < k; ++j) { - if (j > 0) - *ullp <<= 8; - *ullp |= xp[j]; - } - num -= pl; - ucp += pl; - } -} - -void scsiDecodeNonMediumErrPage(unsigned char *resp, - struct scsiNonMediumError *nmep) -{ - int k, j, num, pl, pc, szof; - unsigned char * ucp; - unsigned char * xp; - - memset(nmep, 0, sizeof(*nmep)); - num = (resp[2] << 8) | resp[3]; - ucp = &resp[0] + 4; - szof = sizeof(nmep->counterPC0); - while (num > 3) { - pc = (ucp[0] << 8) | ucp[1]; - pl = ucp[3] + 4; - switch (pc) { - case 0: - nmep->gotPC0 = 1; - k = pl - 4; - xp = ucp + 4; - if (k > szof) { - xp += (k - szof); - k = szof; - } - nmep->counterPC0 = 0; - for (j = 0; j < k; ++j) { - if (j > 0) - nmep->counterPC0 <<= 8; - nmep->counterPC0 |= xp[j]; - } - break; - default: - nmep->gotExtraPC = 1; - break; - } - num -= pl; - ucp += pl; - } -} diff --git a/sm5/scsicmds.cpp b/sm5/scsicmds.cpp deleted file mode 100644 index 1583d83ad..000000000 --- a/sm5/scsicmds.cpp +++ /dev/null @@ -1,1631 +0,0 @@ -/* - * scsicmds.c - * - * Home page of code is: http://smartmontools.sourceforge.net - * - * Copyright (C) 2002-3 Bruce Allen <smartmontools-support@lists.sourceforge.net> - * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org> - * - * Additional SCSI work: - * Copyright (C) 2003 Douglas Gilbert <dougg@torque.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 - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * You should have received a copy of the GNU General Public License - * (for example COPYING); if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * This code was originally developed as a Senior Thesis by Michael Cornwell - * at the Concurrent Systems Laboratory (now part of the Storage Systems - * Research Center), Jack Baskin School of Engineering, University of - * California, Santa Cruz. http://ssrc.soe.ucsc.edu/ - * - * - * In the SCSI world "SMART" is a dead or withdrawn standard. In recent - * SCSI standards (since SCSI-3) it goes under the awkward name of - * "Informational Exceptions" ["IE" or "IEC" (with the "C" for "control")]. - * The relevant information is spread around several SCSI draft - * standards available at http://www.t10.org . Reference is made in the - * code to the following acronyms: - * - SAM [SCSI Architectural model, versions 2 or 3] - * - SPC [SCSI Primary commands, versions 2 or 3] - * - SBC [SCSI Block commands, versions 2] - * - * Some SCSI disk vendors have snippets of "SMART" information in their - * product manuals. - */ - -#include <stdio.h> -#include <string.h> -#include <getopt.h> -#include <unistd.h> -#include <sys/ioctl.h> -#include "scsicmds.h" -#include "utility.h" -#include "extern.h" - -const char *scsicmds_c_cvsid="$Id: scsicmds.cpp,v 1.42 2003/04/29 16:01:09 makisara Exp $" EXTERN_H_CVSID SCSICMDS_H_CVSID; - -/* for passing global control variables */ -extern smartmonctrl *con; - -/* output binary in hex and optionally ascii */ -static void dStrHex(const char* str, int len, int no_ascii) -{ - const char* p = str; - unsigned char c; - char buff[82]; - int a = 0; - const int bpstart = 5; - const int cpstart = 60; - int cpos = cpstart; - int bpos = bpstart; - int i, k; - - if (len <= 0) return; - memset(buff,' ',80); - buff[80]='\0'; - k = sprintf(buff + 1, "%.2x", a); - buff[k + 1] = ' '; - if (bpos >= ((bpstart + (9 * 3)))) - bpos++; - - for(i = 0; i < len; i++) - { - c = *p++; - bpos += 3; - if (bpos == (bpstart + (9 * 3))) - bpos++; - sprintf(&buff[bpos], "%.2x", (int)(unsigned char)c); - buff[bpos + 2] = ' '; - if (no_ascii) - buff[cpos++] = ' '; - else { - if ((c < ' ') || (c >= 0x7f)) - c='.'; - buff[cpos++] = c; - } - if (cpos > (cpstart+15)) - { - pout("%s\n", buff); - bpos = bpstart; - cpos = cpstart; - a += 16; - memset(buff,' ',80); - k = sprintf(buff + 1, "%.2x", a); - buff[k + 1] = ' '; - } - } - if (cpos > cpstart) - { - pout("%s\n", buff); - } -} - -struct scsi_opcode_name { - UINT8 opcode; - const char * name; -}; - -static struct scsi_opcode_name opcode_name_arr[] = { - /* in ascending opcode order */ - {TEST_UNIT_READY, "test unit ready"}, /* 0x00 */ - {REQUEST_SENSE, "request sense"}, /* 0x03 */ - {INQUIRY, "inquiry"}, /* 0x12 */ - {MODE_SELECT, "mode select"}, /* 0x15 */ - {MODE_SENSE, "mode sense"}, /* 0x1a */ - {RECEIVE_DIAGNOSTIC, "receive diagnostic"}, /* 0x1c */ - {SEND_DIAGNOSTIC, "send diagnostic"}, /* 0x1d */ - {LOG_SENSE, "log sense"}, /* 0x4d */ - {MODE_SELECT_10, "mode select(10)"}, /* 0x55 */ - {MODE_SENSE_10, "mode sense(10)"}, /* 0x5a */ -}; - -const char * scsi_get_opcode_name(UINT8 opcode) -{ - int k; - int len = sizeof(opcode_name_arr) / sizeof(opcode_name_arr[0]); - struct scsi_opcode_name * onp; - - for (k = 0; k < len; ++k) { - onp = &opcode_name_arr[k]; - if (opcode == onp->opcode) - return onp->name; - else if (opcode < onp->opcode) - return NULL; - } - return NULL; -} - -/* SCSI command transmission interface function, implementation is OS - * specific. */ -static int do_scsi_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop); - -/* <<<<<<<<<<<<<<<< Start of Linux specific code >>>>>>>>>>>>>>>>> */ -#if 1 -/* Linux specific code, FreeBSD could conditionally compile in CAM stuff - * instead of this. */ - -/* #include <scsi/scsi.h> bypass for now */ -/* #include <scsi/scsi_ioctl.h> bypass for now */ - -#define MAX_DXFER_LEN 1024 /* can be increased if necessary */ -#define SEND_IOCTL_RESP_SENSE_LEN 16 /* ioctl limitation */ -#define DRIVER_SENSE 0x8 /* alternate CHECK CONDITION indication */ - -#ifndef SCSI_IOCTL_SEND_COMMAND -#define SCSI_IOCTL_SEND_COMMAND 1 -#endif -#ifndef SCSI_IOCTL_TEST_UNIT_READY -#define SCSI_IOCTL_TEST_UNIT_READY 2 -#endif - -struct linux_ioctl_send_command -{ - int inbufsize; - int outbufsize; - UINT8 buff[MAX_DXFER_LEN + 16]; -}; - -/* The Linux SCSI_IOCTL_SEND_COMMAND ioctl is primitive and it doesn't - * support: CDB length (guesses it from opcode), resid and timeout. - * Patches pending in Linux 2.4 and 2.5 to extend SEND DIAGNOSTIC timeout - * to 2 hours in order to allow long foreground extended self tests. */ -static int linux_do_scsi_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop) -{ - struct linux_ioctl_send_command wrk; - int status, buff_offset; - size_t len; - - memcpy(wrk.buff, iop->cmnd, iop->cmnd_len); - buff_offset = iop->cmnd_len; - if (con->reportscsiioctl > 0) { - int k; - const unsigned char * ucp = iop->cmnd; - const char * np; - - np = scsi_get_opcode_name(ucp[0]); - pout(" [%s: ", np ? np : "<unknown opcode>"); - for (k = 0; k < iop->cmnd_len; ++k) - pout("%02x ", ucp[k]); - if ((con->reportscsiioctl > 1) && - (DXFER_TO_DEVICE == iop->dxfer_dir) && (iop->dxferp)) { - int trunc = (iop->dxfer_len > 256) ? 1 : 0; - - pout("]\n Outgoing data, len=%d%s:\n", iop->dxfer_len, - (trunc ? " [only first 256 bytes shown]" : "")); - dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1); - } - else - pout("]"); - } - switch (iop->dxfer_dir) { - case DXFER_NONE: - wrk.inbufsize = 0; - wrk.outbufsize = 0; - break; - case DXFER_FROM_DEVICE: - wrk.inbufsize = 0; - if (iop->dxfer_len > MAX_DXFER_LEN) - return -EINVAL; - wrk.outbufsize = iop->dxfer_len; - break; - case DXFER_TO_DEVICE: - if (iop->dxfer_len > MAX_DXFER_LEN) - return -EINVAL; - memcpy(wrk.buff + buff_offset, iop->dxferp, iop->dxfer_len); - wrk.inbufsize = iop->dxfer_len; - wrk.outbufsize = 0; - break; - default: - pout("do_scsi_cmnd_io: bad dxfer_dir\n"); - return -EINVAL; - } - iop->resp_sense_len = 0; - iop->scsi_status = 0; - iop->resid = 0; - status = ioctl(dev_fd, SCSI_IOCTL_SEND_COMMAND , &wrk); - if (-1 == status) { - if (con->reportscsiioctl) - pout(" status=-1, errno=%d [%s]\n", errno, strerror(errno)); - return -errno; - } - if (0 == status) { - if (con->reportscsiioctl > 0) - pout(" status=0\n"); - if (DXFER_FROM_DEVICE == iop->dxfer_dir) { - memcpy(iop->dxferp, wrk.buff, iop->dxfer_len); - if (con->reportscsiioctl > 1) { - int trunc = (iop->dxfer_len > 256) ? 1 : 0; - - pout(" Incoming data, len=%d%s:\n", iop->dxfer_len, - (trunc ? " [only first 256 bytes shown]" : "")); - dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1); - } - } - return 0; - } - iop->scsi_status = status & 0x7e; /* bits 0 and 7 used to be for vendors */ - if (DRIVER_SENSE == ((status >> 24) & 0xff)) - iop->scsi_status = 2; - len = (SEND_IOCTL_RESP_SENSE_LEN < iop->max_sense_len) ? - SEND_IOCTL_RESP_SENSE_LEN : iop->max_sense_len; - if ((SCSI_STATUS_CHECK_CONDITION == iop->scsi_status) && - iop->sensep && (len > 0)) { - memcpy(iop->sensep, wrk.buff, len); - iop->resp_sense_len = len; - if (con->reportscsiioctl > 1) { - pout(" >>> Sense buffer, len=%d:\n", len); - dStrHex(wrk.buff, len , 1); - } - } - if (con->reportscsiioctl) { - if (SCSI_STATUS_CHECK_CONDITION == iop->scsi_status) { - pout(" status=%x: sense_key=%x asc=%x ascq=%x\n", status & 0xff, - wrk.buff[2] & 0xf, wrk.buff[12], wrk.buff[13]); - } - else - pout(" status=0x%x\n", status); - } - if (iop->scsi_status > 0) - return 0; - else { - if (con->reportscsiioctl > 0) - pout(" ioctl status=0x%x but scsi status=0, fail with ENODEV\n", - status); - return -ENODEV; /* give up, assume no device there */ - } -} - -static int do_scsi_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop) -{ - return linux_do_scsi_cmnd_io(dev_fd, iop); -} -#endif -/* <<<<<<<<<<<<<<<< End of Linux specific code >>>>>>>>>>>>>>>>> */ - -void scsi_do_sense_disect(const struct scsi_cmnd_io * io_buf, - struct scsi_sense_disect * out) -{ - memset(out, 0, sizeof(out)); - if ((SCSI_STATUS_CHECK_CONDITION == io_buf->scsi_status) && - (io_buf->resp_sense_len > 7)) { - out->error_code = (io_buf->sensep[0] & 0x7f); - out->sense_key = (io_buf->sensep[2] & 0xf); - if (io_buf->resp_sense_len > 13) { - out->asc = io_buf->sensep[12]; - out->ascq = io_buf->sensep[13]; - } - } -} - -static int scsiSimpleSenseFilter(const struct scsi_sense_disect * sinfo) -{ - if (SCSI_SK_NOT_READY == sinfo->sense_key) - return 1; - else if (SCSI_SK_ILLEGAL_REQUEST == sinfo->sense_key) { - if (SCSI_ASC_UNKNOWN_OPCODE == sinfo->asc) - return 2; - else if (SCSI_ASC_UNKNOWN_FIELD == sinfo->asc) - return 3; - else if (SCSI_ASC_UNKNOWN_PARAM == sinfo->asc) - return 4; - } - return 0; -} - -const char * scsiErrString(int scsiErr) -{ - if (scsiErr < 0) - return strerror(-scsiErr); - switch (scsiErr) { - case 0: - return "no error"; - case 1: - return "device not ready"; - case 2: - return "unsupported scsi opcode"; - case 3: - return "bad value in scsi command"; - case 4: - return "badly formed scsi parameters"; - default: - return "unknown error"; - } -} - -/* Sends LOG SENSE command. Returns 0 if ok, 1 if device NOT READY, 2 if - command not supported, 3 if field (within command) not supported or - returns negated errno. SPC sections 7.6 and 8.2 N.B. Sets PC==1 - to fetch "current cumulative" log pages */ -int scsiLogSense(int device, int pagenum, UINT8 *pBuf, int bufLen) -{ - struct scsi_cmnd_io io_hdr; - struct scsi_sense_disect sinfo; - UINT8 cdb[10]; - UINT8 sense[32]; - int status, res; - - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); - io_hdr.dxfer_dir = DXFER_FROM_DEVICE; - io_hdr.dxfer_len = bufLen; - io_hdr.dxferp = pBuf; - cdb[0] = LOG_SENSE; - cdb[2] = 0x40 | (pagenum & 0x3f); /* Page control (PC)==1 */ - cdb[7] = (bufLen >> 8) & 0xff; - cdb[8] = bufLen & 0xff; - io_hdr.cmnd = cdb; - io_hdr.cmnd_len = sizeof(cdb); - io_hdr.sensep = sense; - io_hdr.max_sense_len = sizeof(sense); - - status = do_scsi_cmnd_io(device, &io_hdr); - scsi_do_sense_disect(&io_hdr, &sinfo); - if ((res = scsiSimpleSenseFilter(&sinfo))) - return res; - if (status > 0) - status = -EIO; - return status; -} - -/* Send MODE SENSE (6 byte) command. Returns 0 if ok, 1 if NOT READY, - * 2 if command not supported (then MODE SENSE(10) should be supported), - * 3 if field in command not supported or returns negated errno. - * SPC sections 7.9 and 8.4 */ -int scsiModeSense(int device, int pagenum, int pc, UINT8 *pBuf, int bufLen) -{ - struct scsi_cmnd_io io_hdr; - struct scsi_sense_disect sinfo; - UINT8 cdb[6]; - UINT8 sense[32]; - int status, res; - - if ((bufLen < 0) || (bufLen > 255)) - return -EINVAL; - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); - io_hdr.dxfer_dir = DXFER_FROM_DEVICE; - io_hdr.dxfer_len = bufLen; - io_hdr.dxferp = pBuf; - cdb[0] = MODE_SENSE; - cdb[2] = (pc << 6) | (pagenum & 0x3f); - cdb[4] = bufLen; - io_hdr.cmnd = cdb; - io_hdr.cmnd_len = sizeof(cdb); - io_hdr.sensep = sense; - io_hdr.max_sense_len = sizeof(sense); - - status = do_scsi_cmnd_io(device, &io_hdr); - scsi_do_sense_disect(&io_hdr, &sinfo); - if ((res = scsiSimpleSenseFilter(&sinfo))) - return res; - if (status > 0) - status = -EIO; - return status; -} - -/* Sends a 6 byte MODE SELECT command. Assumes given pBuf is the response - * from a corresponding 6 byte MODE SENSE command. Such a response should - * have a 4 byte header followed by 0 or more 8 byte block descriptors - * (normally 1) and then 1 mode page. Returns 0 if ok, 1 if NOT READY, - * 2 if command not supported (then MODE SELECT(10) may be supported), - * 3 if field in command not supported, 4 if bad parameter to command - * or returns negated errno. SPC sections 7.7 and 8.4 */ -int scsiModeSelect(int device, int pagenum, int sp, UINT8 *pBuf, int bufLen) -{ - struct scsi_cmnd_io io_hdr; - struct scsi_sense_disect sinfo; - UINT8 cdb[6]; - UINT8 sense[32]; - int status, pg_offset, pg_len, hdr_plus_1_pg, res; - - pg_offset = 4 + pBuf[3]; - if (pg_offset + 2 >= bufLen) - return -EINVAL; - pg_len = pBuf[pg_offset + 1] + 2; - hdr_plus_1_pg = pg_offset + pg_len; - if (hdr_plus_1_pg > bufLen) - return -EINVAL; - pBuf[0] = 0; /* Length of returned mode sense data reserved for SELECT */ - pBuf[pg_offset] &= 0x3f; /* Mask of PS bit from byte 0 of page data */ - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); - io_hdr.dxfer_dir = DXFER_TO_DEVICE; - io_hdr.dxfer_len = hdr_plus_1_pg; - io_hdr.dxferp = pBuf; - cdb[0] = MODE_SELECT; - cdb[1] = 0x10 | (sp & 1); /* set PF (page format) bit always */ - cdb[4] = hdr_plus_1_pg; /* make sure only one page sent */ - io_hdr.cmnd = cdb; - io_hdr.cmnd_len = sizeof(cdb); - io_hdr.sensep = sense; - io_hdr.max_sense_len = sizeof(sense); - - status = do_scsi_cmnd_io(device, &io_hdr); - scsi_do_sense_disect(&io_hdr, &sinfo); - if ((res = scsiSimpleSenseFilter(&sinfo))) - return res; - if (status > 0) - status = -EIO; - return status; -} - -/* MODE SENSE (10 byte). Returns 0 if ok, 1 if NOT READY, 2 if command - * not supported (then MODE SENSE(6) might be supported), 3 if field in - * command not supported or returns negated errno. - * SPC sections 7.10 and 8.4 */ -int scsiModeSense10(int device, int pagenum, int pc, UINT8 *pBuf, int bufLen) -{ - struct scsi_cmnd_io io_hdr; - struct scsi_sense_disect sinfo; - UINT8 cdb[10]; - UINT8 sense[32]; - int status, res; - - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); - io_hdr.dxfer_dir = DXFER_FROM_DEVICE; - io_hdr.dxfer_len = bufLen; - io_hdr.dxferp = pBuf; - cdb[0] = MODE_SENSE_10; - cdb[2] = (pc << 6) | (pagenum & 0x3f); - cdb[7] = (bufLen >> 8) & 0xff; - cdb[8] = bufLen & 0xff; - io_hdr.cmnd = cdb; - io_hdr.cmnd_len = sizeof(cdb); - io_hdr.sensep = sense; - io_hdr.max_sense_len = sizeof(sense); - - status = do_scsi_cmnd_io(device, &io_hdr); - scsi_do_sense_disect(&io_hdr, &sinfo); - if ((res = scsiSimpleSenseFilter(&sinfo))) - return res; - if (status > 0) - status = -EIO; - return status; -} - -/* Sends a 10 byte MODE SELECT command. Assumes given pBuf is the response - * from a corresponding 10 byte MODE SENSE command. Such a response should - * have a 8 byte header followed by 0 or more 8 byte block descriptors - * (normally 1) and then 1 mode page. Returns 0 if ok, 1 NOT REAFY, 2 if - * command not supported (then MODE SELECT(6) may be supported), 3 if field - * in command not supported, 4 if bad parameter to command or returns - * negated errno. SAM sections 7.8 and 8.4 */ -int scsiModeSelect10(int device, int pagenum, int sp, UINT8 *pBuf, int bufLen) -{ - struct scsi_cmnd_io io_hdr; - struct scsi_sense_disect sinfo; - UINT8 cdb[10]; - UINT8 sense[32]; - int status, pg_offset, pg_len, hdr_plus_1_pg, res; - - pg_offset = 8 + (pBuf[6] << 8) + pBuf[7]; - if (pg_offset + 2 >= bufLen) - return -EINVAL; - pg_len = pBuf[pg_offset + 1] + 2; - hdr_plus_1_pg = pg_offset + pg_len; - if (hdr_plus_1_pg > bufLen) - return -EINVAL; - pBuf[0] = 0; - pBuf[1] = 0; /* Length of returned mode sense data reserved for SELECT */ - pBuf[pg_offset] &= 0x3f; /* Mask of PS bit from byte 0 of page data */ - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); - io_hdr.dxfer_dir = DXFER_TO_DEVICE; - io_hdr.dxfer_len = hdr_plus_1_pg; - io_hdr.dxferp = pBuf; - cdb[0] = MODE_SELECT_10; - cdb[1] = 0x10 | (sp & 1); /* set PF (page format) bit always */ - cdb[8] = hdr_plus_1_pg; /* make sure only one page sent */ - io_hdr.cmnd = cdb; - io_hdr.cmnd_len = sizeof(cdb); - io_hdr.sensep = sense; - io_hdr.max_sense_len = sizeof(sense); - - status = do_scsi_cmnd_io(device, &io_hdr); - scsi_do_sense_disect(&io_hdr, &sinfo); - if ((res = scsiSimpleSenseFilter(&sinfo))) - return res; - if (status > 0) - status = -EIO; - return status; -} - -/* Standard INQUIRY returns 0 for ok, anything else is a major problem. - * bufLen should be 36 for unsafe devices (like USB mass storage stuff) - * otherwise they can lock up! SPC sections 7.4 and 8.6 */ -int scsiStdInquiry(int device, UINT8 *pBuf, int bufLen) -{ - struct scsi_cmnd_io io_hdr; - UINT8 cdb[6]; - int status; - - if ((bufLen < 0) || (bufLen > 255)) - return -EINVAL; - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); - io_hdr.dxfer_dir = DXFER_FROM_DEVICE; - io_hdr.dxfer_len = bufLen; - io_hdr.dxferp = pBuf; - cdb[0] = INQUIRY; - cdb[4] = bufLen; - io_hdr.cmnd = cdb; - io_hdr.cmnd_len = sizeof(cdb); - status = do_scsi_cmnd_io(device, &io_hdr); - return status; -} - -/* INQUIRY to fetch Vital Page Data. Returns 0 if ok, 1 if NOT READY - * (unlikely), 2 if command not supported, 3 if field in command not - * supported or returns negated errno. SPC section 7.4 and 8.6 */ -int scsiInquiryVpd(int device, int vpd_page, UINT8 *pBuf, int bufLen) -{ - struct scsi_cmnd_io io_hdr; - struct scsi_sense_disect sinfo; - UINT8 cdb[6]; - UINT8 sense[32]; - int status, res; - - if ((bufLen < 0) || (bufLen > 255)) - return -EINVAL; - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); - io_hdr.dxfer_dir = DXFER_FROM_DEVICE; - io_hdr.dxfer_len = bufLen; - io_hdr.dxferp = pBuf; - cdb[0] = INQUIRY; - cdb[1] = 0x1; /* set EVPD bit (enable Vital Product Data) */ - cdb[2] = vpd_page; - cdb[4] = bufLen; - io_hdr.cmnd = cdb; - io_hdr.cmnd_len = sizeof(cdb); - io_hdr.sensep = sense; - io_hdr.max_sense_len = sizeof(sense); - - status = do_scsi_cmnd_io(device, &io_hdr); - scsi_do_sense_disect(&io_hdr, &sinfo); - if ((res = scsiSimpleSenseFilter(&sinfo))) - return res; - if (status > 0) - status = -EIO; - return status; -} - -/* REQUEST SENSE command. Returns 0 if ok, anything else major problem. - * SPC section 7.24 */ -int scsiRequestSense(int device, struct scsi_sense_disect * sense_info) -{ - struct scsi_cmnd_io io_hdr; - UINT8 cdb[6]; - UINT8 buff[18]; - int status, len; - UINT8 ecode; - - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); - io_hdr.dxfer_dir = DXFER_FROM_DEVICE; - io_hdr.dxfer_len = sizeof(buff); - io_hdr.dxferp = buff; - cdb[0] = REQUEST_SENSE; - cdb[4] = sizeof(buff); - io_hdr.cmnd = cdb; - io_hdr.cmnd_len = sizeof(cdb); - status = do_scsi_cmnd_io(device, &io_hdr); - if ((0 == status) && (sense_info)) { - ecode = buff[0] & 0x7f; - sense_info->error_code = ecode; - sense_info->sense_key = buff[2] & 0xf; - sense_info->asc = 0; - sense_info->ascq = 0; - if ((0x70 == ecode) || (0x71 == ecode)) { - len = buff[7] + 8; - if (len > 13) { - sense_info->asc = buff[12]; - sense_info->ascq = buff[13]; - } - } - } - return status; -} - -/* SEND DIAGNOSTIC command. Returns 0 if ok, 1 if NOT READY, 2 if command - * not supported, 3 if field in command not supported or returns negated - * errno. SPC section 7.25 */ -int scsiSendDiagnostic(int device, int functioncode, UINT8 *pBuf, int bufLen) -{ - struct scsi_cmnd_io io_hdr; - struct scsi_sense_disect sinfo; - UINT8 cdb[6]; - UINT8 sense[32]; - int status, res; - - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); - io_hdr.dxfer_dir = bufLen ? DXFER_TO_DEVICE: DXFER_NONE; - io_hdr.dxfer_len = bufLen; - io_hdr.dxferp = pBuf; - cdb[0] = SEND_DIAGNOSTIC; - if (SCSI_DIAG_DEF_SELF_TEST == functioncode) - cdb[1] = 0x4; /* SelfTest bit */ - else if (SCSI_DIAG_NO_SELF_TEST != functioncode) - cdb[1] = (functioncode & 0x7) << 5; /* SelfTest _code_ */ - else /* SCSI_DIAG_NO_SELF_TEST == functioncode */ - cdb[1] = 0x10; /* PF bit */ - cdb[3] = (bufLen >> 8) & 0xff; - cdb[4] = bufLen & 0xff; - io_hdr.cmnd = cdb; - io_hdr.cmnd_len = sizeof(cdb); - io_hdr.sensep = sense; - io_hdr.max_sense_len = sizeof(sense); - io_hdr.timeout = 5 * 60 * 60; /* five hours because a foreground - extended self tests can take 1 hour plus */ - - status = do_scsi_cmnd_io(device, &io_hdr); - scsi_do_sense_disect(&io_hdr, &sinfo); - if ((res = scsiSimpleSenseFilter(&sinfo))) - return res; - if (status > 0) - status = -EIO; - return status; -} - -/* RECEIVE DIAGNOSTIC command. Returns 0 if ok, 1 if NOT READY, 2 if - * command not supported, 3 if field in command not supported or returns - * negated errno. SPC section 7.17 */ -int scsiReceiveDiagnostic(int device, int pcv, int pagenum, UINT8 *pBuf, - int bufLen) -{ - struct scsi_cmnd_io io_hdr; - struct scsi_sense_disect sinfo; - UINT8 cdb[6]; - UINT8 sense[32]; - int status, res; - - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); - io_hdr.dxfer_dir = DXFER_FROM_DEVICE; - io_hdr.dxfer_len = bufLen; - io_hdr.dxferp = pBuf; - cdb[0] = RECEIVE_DIAGNOSTIC; - cdb[1] = pcv; - cdb[2] = pagenum; - cdb[3] = (bufLen >> 8) & 0xff; - cdb[4] = bufLen & 0xff; - io_hdr.cmnd = cdb; - io_hdr.cmnd_len = sizeof(cdb); - io_hdr.sensep = sense; - io_hdr.max_sense_len = sizeof(sense); - - status = do_scsi_cmnd_io(device, &io_hdr); - scsi_do_sense_disect(&io_hdr, &sinfo); - if ((res = scsiSimpleSenseFilter(&sinfo))) - return res; - if (status > 0) - status = -EIO; - return status; -} - -/* TEST UNIT READY command. SPC section 7.28 (probably in SBC as well) */ -static int _testunitready(int device, struct scsi_sense_disect * sinfo) -{ - struct scsi_cmnd_io io_hdr; - UINT8 cdb[6]; - UINT8 sense[32]; - int status; - - memset(&io_hdr, 0, sizeof(io_hdr)); - memset(cdb, 0, sizeof(cdb)); - io_hdr.dxfer_dir = DXFER_NONE; - io_hdr.dxfer_len = 0; - io_hdr.dxferp = NULL; - cdb[0] = TEST_UNIT_READY; - io_hdr.cmnd = cdb; - io_hdr.cmnd_len = sizeof(cdb); - io_hdr.sensep = sense; - io_hdr.max_sense_len = sizeof(sense); - - status = do_scsi_cmnd_io(device, &io_hdr); - scsi_do_sense_disect(&io_hdr, sinfo); - return status; -} - -/* Returns 0 for device responds and media ready, 1 for device responds and - media not ready, or returns a negated errno value */ -int scsiTestUnitReady(int device) -{ - struct scsi_sense_disect sinfo; - int status; - - status = _testunitready(device, &sinfo); - if (SCSI_SK_NOT_READY == sinfo.sense_key) - return 1; - else if (SCSI_SK_UNIT_ATTENTION == sinfo.sense_key) { - /* power on reset, media changed, ok ... try again */ - status = _testunitready(device, &sinfo); - if (SCSI_SK_NOT_READY == sinfo.sense_key) - return 1; - } - return status; -} - -/* Offset into mode sense (6 or 10 byte) response that actual mode page - * starts at (relative to resp[0]). Returns -1 if problem */ -static int scsiModePageOffset(const UINT8 * resp, int len, int modese_10) -{ - int resp_len, bd_len; - int offset = -1; - - if (resp) { - if (modese_10) { - resp_len = (resp[0] << 8) + resp[1] + 2; - bd_len = (resp[6] << 8) + resp[7]; - offset = bd_len + 8; - } else { - resp_len = resp[0] + 1; - bd_len = resp[3]; - offset = bd_len + 4; - } - if ((offset + 2) > len) { - pout("scsiModePageOffset: raw_curr too small, offset=%d " - "resp_len=%d bd_len=%d\n", offset, resp_len, bd_len); - offset = -1; - } else if ((offset + 2) > resp_len) { - pout("scsiModePageOffset: bad resp_len=%d offset=%d bd_len=%d\n", - resp_len, offset, bd_len); - offset = -1; - } - } - return offset; -} - -/* IEC mode page byte 2 bit masks */ -#define DEXCPT_ENABLE 0x08 -#define EWASC_ENABLE 0x10 -#define DEXCPT_DISABLE 0xf7 -#define EWASC_DISABLE 0xef -#define TEST_DISABLE 0xfb - -int scsiFetchIECmpage(int device, struct scsi_iec_mode_page *iecp) -{ - int err; - - memset(iecp, 0, sizeof(*iecp)); - iecp->requestedCurrent = 1; - if ((err = scsiModeSense(device, INFORMATIONAL_EXCEPTIONS_CONTROL, - 0, iecp->raw_curr, sizeof(iecp->raw_curr)))) { - if (2 == err) { /* opcode no good so try 10 byte mode sense */ - err = scsiModeSense10(device, INFORMATIONAL_EXCEPTIONS_CONTROL, - 0, iecp->raw_curr, sizeof(iecp->raw_curr)); - if (0 == err) - iecp->modese_10 = 1; - else - return err; - } else - return err; - } - iecp->gotCurrent = 1; - iecp->requestedChangeable = 1; - if (iecp->modese_10) { - if (0 == scsiModeSense10(device, INFORMATIONAL_EXCEPTIONS_CONTROL, - 1, iecp->raw_chg, sizeof(iecp->raw_chg))) - iecp->gotChangeable = 1; - } else { - if (0 == scsiModeSense(device, INFORMATIONAL_EXCEPTIONS_CONTROL, - 1, iecp->raw_chg, sizeof(iecp->raw_chg))) - iecp->gotChangeable = 1; - } - return 0; -} - -/* Return 0 if ok, -EINVAL if problems */ -int scsiDecodeIEModePage(const struct scsi_iec_mode_page *iecp, - UINT8 *byte_2p, UINT8 *mrie_p, unsigned int *interval_timer_p, - unsigned int *report_count_p) -{ - int offset, len; - - if (iecp && iecp->gotCurrent) { - offset = scsiModePageOffset(iecp->raw_curr, sizeof(iecp->raw_curr), - iecp->modese_10); - if (offset >= 0) { - len = iecp->raw_curr[offset + 1] + 2; - if (byte_2p) - *byte_2p = iecp->raw_curr[offset + 2]; - if (mrie_p) - *mrie_p = iecp->raw_curr[offset + 3] & 0xf; - if (interval_timer_p && (len > 7)) - *interval_timer_p = (iecp->raw_curr[offset + 4] << 24) + - (iecp->raw_curr[offset + 5] << 16) + - (iecp->raw_curr[offset + 6] << 8) + - iecp->raw_curr[offset + 7]; - else if (interval_timer_p) - *interval_timer_p = 0; - if (report_count_p && (len > 11)) - *report_count_p = (iecp->raw_curr[offset + 8] << 24) + - (iecp->raw_curr[offset + 9] << 16) + - (iecp->raw_curr[offset + 10] << 8) + - iecp->raw_curr[offset + 11]; - else if (report_count_p) - *report_count_p = 0; - return 0; - } else - return -EINVAL; - } else - return -EINVAL; -} - -int scsi_IsExceptionControlEnabled(const struct scsi_iec_mode_page *iecp) -{ - int offset; - - if (iecp && iecp->gotCurrent) { - offset = scsiModePageOffset(iecp->raw_curr, sizeof(iecp->raw_curr), - iecp->modese_10); - if (offset >= 0) - return (iecp->raw_curr[offset + 2] & DEXCPT_ENABLE) ? 0 : 1; - else - return 0; - } else - return 0; -} - -int scsi_IsWarningEnabled(const struct scsi_iec_mode_page *iecp) -{ - int offset; - - if (iecp && iecp->gotCurrent) { - offset = scsiModePageOffset(iecp->raw_curr, sizeof(iecp->raw_curr), - iecp->modese_10); - if (offset >= 0) - return (iecp->raw_curr[offset + 2] & EWASC_ENABLE) ? 1 : 0; - else - return 0; - } else - return 0; -} - -/* set EWASC and clear PERF, EBF, DEXCPT TEST and LOGERR */ -#define SCSI_IEC_MP_BYTE2_ENABLED 0x10 -#define SCSI_IEC_MP_BYTE2_TEST_MASK 0x4 -/* exception/warning via an unrequested REQUEST SENSE command */ -#define SCSI_IEC_MP_MRIE 6 -#define SCSI_IEC_MP_INTERVAL_T 0 -#define SCSI_IEC_MP_REPORT_COUNT 1 - -/* Try to set (or clear) both Exception Control and Warning in the IE - * mode page subject to the "changeable" mask. The object pointed to - * by iecp is (possibly) inaccurate after this call, therefore - * scsiFetchIECmpage() should be called again if the IEC mode page - * is to be re-examined. - * When -r ioctl is invoked 3 or more time on 'smartctl -s on ...' - * then set the TEST bit (causes asc,ascq pair of 0x5d,0xff). */ -int scsiSetExceptionControlAndWarning(int device, int enabled, - const struct scsi_iec_mode_page *iecp) -{ - int k, offset, err; - UINT8 rout[SCSI_IECMP_RAW_LEN]; - int sp, eCEnabled, wEnabled; - - if ((! iecp) || (! iecp->gotCurrent)) - return -EINVAL; - offset = scsiModePageOffset(iecp->raw_curr, sizeof(iecp->raw_curr), - iecp->modese_10); - if (offset < 0) - return -EINVAL; - memcpy(rout, iecp->raw_curr, SCSI_IECMP_RAW_LEN); - rout[0] = 0; /* Mode Data Length reserved in MODE SELECTs */ - if (iecp->modese_10) - rout[1] = 0; - sp = (rout[offset] & 0x80) ? 1 : 0; /* PS bit becomes 'SELECT's SP bit */ - rout[offset] &= 0x7f; /* mask off PS bit */ - if (enabled) { - rout[offset + 2] = SCSI_IEC_MP_BYTE2_ENABLED; - if (con->reportscsiioctl > 2) - rout[offset + 2] |= SCSI_IEC_MP_BYTE2_TEST_MASK; - rout[offset + 3] = SCSI_IEC_MP_MRIE; - rout[offset + 4] = (SCSI_IEC_MP_INTERVAL_T >> 24) & 0xff; - rout[offset + 5] = (SCSI_IEC_MP_INTERVAL_T >> 16) & 0xff; - rout[offset + 6] = (SCSI_IEC_MP_INTERVAL_T >> 8) & 0xff; - rout[offset + 7] = SCSI_IEC_MP_INTERVAL_T & 0xff; - rout[offset + 8] = (SCSI_IEC_MP_REPORT_COUNT >> 24) & 0xff; - rout[offset + 9] = (SCSI_IEC_MP_REPORT_COUNT >> 16) & 0xff; - rout[offset + 10] = (SCSI_IEC_MP_REPORT_COUNT >> 8) & 0xff; - rout[offset + 11] = SCSI_IEC_MP_REPORT_COUNT & 0xff; - if (iecp->gotChangeable) { - UINT8 chg2 = iecp->raw_chg[offset + 2]; - - rout[offset + 2] = chg2 ? (rout[offset + 2] & chg2) : - iecp->raw_curr[offset + 2]; - for (k = 3; k < 12; ++k) { - if (0 == iecp->raw_chg[offset + k]) - rout[offset + k] = iecp->raw_curr[offset + k]; - } - } - if (0 == memcmp(&rout[offset + 2], &iecp->raw_chg[offset + 2], 10)) { - if (con->reportscsiioctl > 0) - pout("scsiSetExceptionControlAndWarning: already enabled\n"); - return 0; - } - } else { /* disabling Exception Control and (temperature) Warnings */ - eCEnabled = (rout[offset + 2] & DEXCPT_ENABLE) ? 0 : 1; - wEnabled = (rout[offset + 2] & EWASC_ENABLE) ? 1 : 0; - if ((! eCEnabled) && (! wEnabled)) { - if (con->reportscsiioctl > 0) - pout("scsiSetExceptionControlAndWarning: already disabled\n"); - return 0; /* nothing to do, leave other setting alone */ - } - if (wEnabled) - rout[offset + 2] &= EWASC_DISABLE; - if (eCEnabled) { - if (iecp->gotChangeable && - (iecp->raw_chg[offset + 2] & DEXCPT_ENABLE)) - rout[offset + 2] |= DEXCPT_ENABLE; - rout[offset + 2] &= TEST_DISABLE;/* clear TEST bit for spec */ - } - } - if (iecp->modese_10) - err = scsiModeSelect10(device, INFORMATIONAL_EXCEPTIONS_CONTROL, - sp, rout, sizeof(rout)); - else - err = scsiModeSelect(device, INFORMATIONAL_EXCEPTIONS_CONTROL, - sp, rout, sizeof(rout)); - return err; -} - -int scsiGetTemp(int device, UINT8 *currenttemp, UINT8 *triptemp) -{ - UINT8 tBuf[252]; - int err; - - if ((err = scsiLogSense(device, TEMPERATURE_PAGE, tBuf, sizeof(tBuf)))) { - *currenttemp = 0; - *triptemp = 0; - pout("Log Sense for temperature failed [%s]\n", scsiErrString(err)); - return 1; - } - *currenttemp = tBuf[9]; - *triptemp = tBuf[15]; - return 0; -} - -/* Read informational exception log page or Request Sense response. - * Fetching asc/ascq code potentially flagging an exception or warning. - * Returns 0 if ok, else error number. A current temperature of 255 - * (Centigrade) if for temperature not available. */ -int scsiCheckIE(int device, int method, int hasTempLogPage, - UINT8 *asc, UINT8 *ascq, UINT8 *currenttemp) -{ - UINT8 tBuf[252]; - struct scsi_sense_disect sense_info; - int err; - int temperatureSet = 0; - unsigned short pagesize; - UINT8 currTemp, tripTemp; - - *asc = 0; - *ascq = 0; - *currenttemp = 0; - memset(&sense_info, 0, sizeof(sense_info)); - if (method == CHECK_SMART_BY_LGPG_2F) { - if ((err = scsiLogSense(device, IE_LOG_PAGE, tBuf, sizeof(tBuf)))) { - pout("Log Sense failed, IE page [%s]\n", scsiErrString(err)); - return 5; - } - pagesize = (unsigned short) (tBuf[2] << 8) | tBuf[3]; - if ((pagesize < 4) || tBuf[4] || tBuf[5]) { - pout("Log Sense failed, IE page, bad parameter code or length\n"); - return 5; - } - if (tBuf[7] > 1) { - sense_info.asc = tBuf[8]; - sense_info.ascq = tBuf[9]; - if (tBuf[7] > 2) { - *currenttemp = tBuf[10]; - temperatureSet = 1; - } - } - } - if (0 == sense_info.asc) { - /* ties in with MRIE field of 6 in IEC mode page (0x1c) */ - if ((err = scsiRequestSense(device, &sense_info))) { - pout("Request Sense failed, [%s]\n", scsiErrString(err)); - return 5; - } - } - *asc = sense_info.asc; - *ascq = sense_info.ascq; - if ((! temperatureSet) && hasTempLogPage) { - if (0 == scsiGetTemp(device, &currTemp, &tripTemp)) - *currenttemp = currTemp; - } - return 0; -} - -static const char * TapeAlertsMessageTable[]= { - " ", - "The tape drive is having problems reading data. No data has been lost, " - "but there has been a reduction in the performance of the tape.", - "The tape drive is having problems writing data. No data has been lost, " - "but there has been a reduction in the performance of the tape.", - "The operation has stopped because an error has occurred while reading " - "or writing data which the drive cannot correct.", - "Your data is at risk:\n1. Copy any data you require from this tape. \n" - "2. Do not use this tape again.\n" - "3. Restart the operation with a different tape.", - "The tape is damaged or the drive is faulty. Call the tape drive " - "supplier helpline.", - "The tape is from a faulty batch or the tape drive is faulty:\n" - "1. Use a good tape to test the drive.\n" - "2. If problem persists, call the tape drive supplier helpline.", - "The tape cartridge has reached the end of its calculated useful life: \n" - "1. Copy data you need to another tape.\n" - "2. Discard the old tape.", - "The tape cartridge is not data-grade. Any data you back up to the tape " - "is at risk. Replace the cartridge with a data-grade tape.", - "You are trying to write to a write-protected cartridge. Remove the " - "write-protection or use another tape.", - "You cannot eject the cartridge because the tape drive is in use. Wait " - "until the operation is complete before ejecting the cartridge.", - "The tape in the drive is a cleaning cartridge.", - "You have tried to load a cartridge of a type which is not supported " - "by this drive.", - "The operation has failed because the tape in the drive has snapped:\n" - "1. Discard the old tape.\n" - "2. Restart the operation with a different tape.", - "The operation has failed because the tape in the drive has snapped:\n" - "1. Do not attempt to extract the tape cartridge\n" - "2. Call the tape drive supplier helpline.", - "The memory in the tape cartridge has failed, which reduces performance. " - "Do not use the cartridge for further backup operations.", - "The operation has failed because the tape cartridge was manually " - "ejected while the tape drive was actively writing or reading.", - "You have loaded of a type that is read-only in this drive. The " - "cartridge will appear as write-protected.", - "The directory on the tape cartridge has been corrupted. File search " - "performance will be degraded. The tape directory can be rebuilt " - "by reading all the data on the cartridge.", - "The tape cartridge is nearing the end of its calculated life. It is " - "recommended that you:\n" - "1. Use another tape cartridge for your next backup.\n" - "2. Store this tape in a safe place in case you need to restore " - "data from it.", - "The tape drive needs cleaning:\n" - "1. If the operation has stopped, eject the tape and clean the drive.\n" - "2. If the operation has not stopped, wait for it to finish and then " - "clean the drive. Check the tape drive users manual for device " - "specific cleaning instructions.", - "The tape drive is due for routine cleaning:\n" - "1. Wait for the current operation to finish.\n" - "2. The use a cleaning cartridge. Check the tape drive users manual " - "for device specific cleaning instructions.", - "The last cleaning cartridge used in the tape drive has worn out:\n" - "1. Discard the worn out cleaning cartridge.\n" - "2. Wait for the current operation to finish.\n" - "3. Then use a new cleaning cartridge.", - "The last cleaning cartridge used in the tape drive was an invalid type:\n" - "1. Do not use this cleaning cartridge in this drive.\n" - "2. Wait for the current operation to finish.\n" - "3. Then use a new cleaning cartridge.", - "The tape drive has requested a retention operation", - "A redundant interface port on the tape drive has failed", - "A tape drive cooling fan has failed", - "A redundant power supply has failed inside the tape drive enclosure. " - "Check the enclosure users manual for instructions on replacing the " - "failed power supply.", - "The tape drive power consumption is outside the specified range.", - "Preventive maintenance of the tape drive is required. Check the tape " - "drive users manual for device specific preventive maintenance " - "tasks or call the tape drive supplier helpline.", - "The tape drive has a hardware fault:\n" - "1. Eject the tape or magazine.\n" - "2. Reset the drive.\n" - "3. Restart the operation.", - "The tape drive has a hardware fault:\n" - "1. Turn the tape drive off and then on again.\n" - "2. Restart the operation.\n" - "3. If the problem persists, call the tape drive supplier helpline.\n" - " Check the tape drive users manual for device specific instructions " - "on turning the device power in and off.", - "The tape drive has a problem with the host interface:\n" - "1. Check the cables and cable connections.\n" - "2. Restart the operation.", - "The operation has failed:\n" - "1. Eject the tape or magazine.\n" - "2. Insert the tape or magazine again.\n" - "3. Restart the operation.", - "The firmware download has failed because you have tried to use the " - "incorrect firmware for this tape drive. Obtain the correct " - "firmware and try again.", - "Environmental conditions inside the tape drive are outside the " - "specified humidity range.", - "Environmental conditions inside the tape drive are outside the " - "specified temperature range.", - "The voltage supply to the tape drive is outside the specified range.", - "A hardware failure of the tape drive is predicted. Call the tape " - "drive supplier helpline.", - "The tape drive may have a fault. Check for availability of diagnostic " - "information and run extended diagnostics if applicable. Check the " - "tape drive users manual for instruction on running extended " - "diagnostic tests and retrieving diagnostic data", - "The changer mechanism is having difficulty communicating with the tape " - "drive:\n" - "1. Turn the autoloader off then on.\n" - "2. Restart the operation.\n" - "3. If problem persists, call the tape drive supplier helpline.", - "A tape has been left in the autoloader by a previous hardware fault:\n" - "1. Insert an empty magazine to clear the fault.\n" - "2. If the fault does not clear, turn the autoloader off and then " - "on again.\n" - "3. If the problem persists, call the tape drive supplier helpline.", - "There is a problem with the autoloader mechanism.", - "The operation has failed because the autoloader door is open:\n" - "1. Clear any obstructions from the autoloader door.\n" - "2. Eject the magazine and then insert it again.\n" - "3. If the fault does not clear, turn the autoloader off and then " - "on again.\n" - "4. If the problem persists, call the tape drive supplier helpline.", - "The autoloader has a hardware fault:\n" - "1. Turn the autoloader off and then on again.\n" - "2. Restart the operation.\n" - "3. If the problem persists, call the tape drive supplier helpline.\n" - " Check the autoloader users manual for device specific instructions " - "on turning the device power on and off.", - "The autoloader cannot operate without the magazine,\n" - "1. Insert the magazine into the autoloader.\n" - "2. Restart the operation.", - "A hardware failure of the changer mechanism is predicted. Call the " - "tape drive supplier helpline.", - " ", - " ", - " ", - "Media statistics have been lost at some time in the past", - "The tape directory on the tape cartridge just unloaded has been " - "corrupted. File search performance will be degraded. The tape " - "directory can be rebuilt by reading all the data.", - "The tape just unloaded could not write its system area successfully:\n" - "1. Copy data to another tape cartridge.\n" - "2. Discard the old cartridge.", - "The tape system are could not be read successfully at load time:\n" - "1. Copy data to another tape cartridge.\n" - "2. Discard the old cartridge.", - "The start or data could not be found on the tape:\n" - "1. Check you are using the correct format tape.\n" - "2. Discard the tape or return the tape to you supplier", - }; - -const char * scsiTapeAlertsTapeDevice(unsigned short code) -{ - const int num = sizeof(TapeAlertsMessageTable) / - sizeof(TapeAlertsMessageTable[0]); - - return (code < num) ? TapeAlertsMessageTable[code] : "Unknown Alert"; -} - -static const char * ChangerTapeAlertsMessageTable[]= { - " ", - "The library mechanism is having difficulty communicating with the drive:\n" - "1. Turn the library off then on.\n" - "2. Restart the operation.\n" - "3. If the problem persists, call the library supplier help line.", - "There is a problem with the library mechanism. If problem persists,\n" - "call the library supplier help line.", - "The library has a hardware fault:\n" - "1. Reset the library.\n" - "2. Restart the operation.\n" - "Check the library users manual for device specific instructions on resetting\n" - "the device.", - "The library has a hardware fault:\n" - "1. Turn the library off then on again.\n" - "2. Restart the operation.\n" - "3. If the problem persists, call the library supplier help line.\n" - "Check the library users manual for device specific instructions on turning the\n" - "device power on and off.", - "The library mechanism may have a hardware fault.\n" - "Run extended diagnostics to verify and diagnose the problem. Check the library\n" - "users manual for device specific instructions on running extended diagnostic\n" - "tests.", - "The library has a problem with the host interface:\n" - "1. Check the cables and connections.\n" - "2. Restart the operation.", - "A hardware failure of the library is predicted. Call the library\n" - "supplier help line.", - "Preventive maintenance of the library is required.\n" - "Check the library users manual for device specific preventative maintenance\n" - "tasks, or call your library supplier help line.", - "General environmental conditions inside the library are outside the\n" - "specified humidity range.", - "General environmental conditions inside the library are outside the\n" - "specified temperature range.", - "The voltage supply to the library is outside the specified range.\n" - "There is a potential problem with the power supply or failure of\n" - "a redundant power supply.", - "A cartridge has been left inside the library by a previous hardware\n" - "fault:\n" - "1. Insert an empty magazine to clear the fault.\n" - "2. If the fault does not clear, turn the library off and then on again.\n" - "3. If the problem persists, call the library supplier help line.", - "There is a potential problem with the drive ejecting cartridges or with\n" - "the library mechanism picking a cartridge from a slot.\n" - "1. No action needs to be taken at this time.\n" - "2. If the problem persists, call the library supplier help line.", - "There is a potential problem with the library mechanism placing a cartridge\n" - "into a slot.\n" - "1. No action needs to be taken at this time.\n" - "2. If the problem persists, call the library supplier help line.", - "There is a potential problem with the drive or the library mechanism\n" - "loading cartridges, or an incompatible cartridge.", - "The library has failed because the door is open:\n" - "1. Clear any obstructions from the library door.\n" - "2. Close the library door.\n" - "3. If the problem persists, call the library supplier help line.", - "There is a mechanical problem with the library media import/export\n" - "mailslot.", - "The library cannot operate without the magazine.\n" - "1. Insert the magazine into the library.\n" - "2. Restart the operation.", - "Library security has been compromised.", - "The library security mode has been changed.\n" - "The library has either been put into secure mode, or the library has exited\n" - "the secure mode.\n" - "This is for information purposes only. No action is required.", - "The library has been manually turned offline and is unavailable for use.", - "A drive inside the library has been taken offline.\n" - "This is for information purposes only. No action is required.", - "There is a potential problem with the bar code label or the scanner\n" - "hardware in the library mechanism.\n" - "1. No action needs to be taken at this time.\n" - "2. If the problem persists, call the library supplier help line.", - "The library has detected an inconsistency in its inventory.\n" - "1. Redo the library inventory to correct inconsistency.\n" - "2. Restart the operation.\n" - "Check the applications users manual or the hardware users manual for\n" - "specific instructions on redoing the library inventory.", - "A library operation has been attempted that is invalid at this time.", - "A redundant interface port on the library has failed.", - "A library cooling fan has failed.", - "A redundant power supply has failed inside the library. Check the\n" - "library users manual for instructions on replacing the failed power supply.", - "The library power consumption is outside the specified range.", - "A failure has occurred in the cartridge pass-through mechanism between\n" - "two library modules.", - "A cartridge has been left in the pass-through mechanism from a previous\n" - "hardware fault. Check the library users guide for instructions on clearing\n" - "this fault.", - "The library was unable to read the bar code on a cartridge.", -}; - -const char * scsiTapeAlertsChangerDevice(unsigned short code) -{ - const int num = sizeof(ChangerTapeAlertsMessageTable) / - sizeof(ChangerTapeAlertsMessageTable[0]); - - return (code < num) ? ChangerTapeAlertsMessageTable[code] : "Unknown Alert"; -} - - -/* this is a subset of the SCSI additional sense code strings indexed - * by "ascq" for the case when asc==SCSI_ASC_IMPENDING_FAILURE (0x5d) - */ -static const char * strs_for_asc_5d[] = { - /* 0x00 */ "FAILURE PREDICTION THRESHOLD EXCEEDED", - "MEDIA FAILURE PREDICTION THRESHOLD EXCEEDED", - "LOGICAL UNIT FAILURE PREDICTION THRESHOLD EXCEEDED", - "SPARE AREA EXHAUSTION PREDICTION THRESHOLD EXCEEDED", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - /* 0x10 */ "HARDWARE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE", - "HARDWARE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH", - "HARDWARE IMPENDING FAILURE DATA ERROR RATE TOO HIGH", - "HARDWARE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH", - "HARDWARE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS", - "HARDWARE IMPENDING FAILURE ACCESS TIMES TOO HIGH", - "HARDWARE IMPENDING FAILURE START UNIT TIMES TOO HIGH", - "HARDWARE IMPENDING FAILURE CHANNEL PARAMETRICS", - "HARDWARE IMPENDING FAILURE CONTROLLER DETECTED", - "HARDWARE IMPENDING FAILURE THROUGHPUT PERFORMANCE", - "HARDWARE IMPENDING FAILURE SEEK TIME PERFORMANCE", - "HARDWARE IMPENDING FAILURE SPIN-UP RETRY COUNT", - "HARDWARE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT", - "", - "", - "", - /* 0x20 */ "CONTROLLER IMPENDING FAILURE GENERAL HARD DRIVE FAILURE", - "CONTROLLER IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH", - "CONTROLLER IMPENDING FAILURE DATA ERROR RATE TOO HIGH", - "CONTROLLER IMPENDING FAILURE SEEK ERROR RATE TOO HIGH", - "CONTROLLER IMPENDING FAILURE TOO MANY BLOCK REASSIGNS", - "CONTROLLER IMPENDING FAILURE ACCESS TIMES TOO HIGH", - "CONTROLLER IMPENDING FAILURE START UNIT TIMES TOO HIGH", - "CONTROLLER IMPENDING FAILURE CHANNEL PARAMETRICS", - "CONTROLLER IMPENDING FAILURE CONTROLLER DETECTED", - "CONTROLLER IMPENDING FAILURE THROUGHPUT PERFORMANCE", - "CONTROLLER IMPENDING FAILURE SEEK TIME PERFORMANCE", - "CONTROLLER IMPENDING FAILURE SPIN-UP RETRY COUNT", - "CONTROLLER IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT", - "", - "", - "", - /* 0x30 */ "DATA CHANNEL IMPENDING FAILURE GENERAL HARD DRIVE FAILURE", - "DATA CHANNEL IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH", - "DATA CHANNEL IMPENDING FAILURE DATA ERROR RATE TOO HIGH", - "DATA CHANNEL IMPENDING FAILURE SEEK ERROR RATE TOO HIGH", - "DATA CHANNEL IMPENDING FAILURE TOO MANY BLOCK REASSIGNS", - "DATA CHANNEL IMPENDING FAILURE ACCESS TIMES TOO HIGH", - "DATA CHANNEL IMPENDING FAILURE START UNIT TIMES TOO HIGH", - "DATA CHANNEL IMPENDING FAILURE CHANNEL PARAMETRICS", - "DATA CHANNEL IMPENDING FAILURE CONTROLLER DETECTED", - "DATA CHANNEL IMPENDING FAILURE THROUGHPUT PERFORMANCE", - "DATA CHANNEL IMPENDING FAILURE SEEK TIME PERFORMANCE", - "DATA CHANNEL IMPENDING FAILURE SPIN-UP RETRY COUNT", - "DATA CHANNEL IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT", - "", - "", - "", - /* 0x40 */ "SERVO IMPENDING FAILURE GENERAL HARD DRIVE FAILURE", - "SERVO IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH", - "SERVO IMPENDING FAILURE DATA ERROR RATE TOO HIGH", - "SERVO IMPENDING FAILURE SEEK ERROR RATE TOO HIGH", - "SERVO IMPENDING FAILURE TOO MANY BLOCK REASSIGNS", - "SERVO IMPENDING FAILURE ACCESS TIMES TOO HIGH", - "SERVO IMPENDING FAILURE START UNIT TIMES TOO HIGH", - "SERVO IMPENDING FAILURE CHANNEL PARAMETRICS", - "SERVO IMPENDING FAILURE CONTROLLER DETECTED", - "SERVO IMPENDING FAILURE THROUGHPUT PERFORMANCE", - "SERVO IMPENDING FAILURE SEEK TIME PERFORMANCE", - "SERVO IMPENDING FAILURE SPIN-UP RETRY COUNT", - "SERVO IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT", - "", - "", - "", - /* 0x50 */ "SPINDLE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE", - "SPINDLE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH", - "SPINDLE IMPENDING FAILURE DATA ERROR RATE TOO HIGH", - "SPINDLE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH", - "SPINDLE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS", - "SPINDLE IMPENDING FAILURE ACCESS TIMES TOO HIGH", - "SPINDLE IMPENDING FAILURE START UNIT TIMES TOO HIGH", - "SPINDLE IMPENDING FAILURE CHANNEL PARAMETRICS", - "SPINDLE IMPENDING FAILURE CONTROLLER DETECTED", - "SPINDLE IMPENDING FAILURE THROUGHPUT PERFORMANCE", - "SPINDLE IMPENDING FAILURE SEEK TIME PERFORMANCE", - "SPINDLE IMPENDING FAILURE SPIN-UP RETRY COUNT", - "SPINDLE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT", - "", - "", - "", - /* 0x60 */ "FIRMWARE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE", - "FIRMWARE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH", - "FIRMWARE IMPENDING FAILURE DATA ERROR RATE TOO HIGH", - "FIRMWARE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH", - "FIRMWARE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS", - "FIRMWARE IMPENDING FAILURE ACCESS TIMES TOO HIGH", - "FIRMWARE IMPENDING FAILURE START UNIT TIMES TOO HIGH", - "FIRMWARE IMPENDING FAILURE CHANNEL PARAMETRICS", - "FIRMWARE IMPENDING FAILURE CONTROLLER DETECTED", - "FIRMWARE IMPENDING FAILURE THROUGHPUT PERFORMANCE", - "FIRMWARE IMPENDING FAILURE SEEK TIME PERFORMANCE", - "FIRMWARE IMPENDING FAILURE SPIN-UP RETRY COUNT", - /* 0x6c */ "FIRMWARE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"}; - - -/* this is a subset of the SCSI additional sense code strings indexed - * * by "ascq" for the case when asc==SCSI_ASC_WARNING (0xb) - * */ -static const char * strs_for_asc_b[] = { - /* 0x00 */ "WARNING", - "WARNING - SPECIFIED TEMPERATURE EXCEEDED", - "WARNING - ENCLOSURE DEGRADED"}; - -static char spare_buff[128]; - -const char * scsiGetIEString(UINT8 asc, UINT8 ascq) -{ - const char * rp; - - if (SCSI_ASC_IMPENDING_FAILURE == asc) { - if (ascq == 0xff) - return "FAILURE PREDICTION THRESHOLD EXCEEDED (FALSE)"; - else if (ascq < - (sizeof(strs_for_asc_5d) / sizeof(strs_for_asc_5d[0]))) { - rp = strs_for_asc_5d[ascq]; - if (strlen(rp) > 0) - return rp; - } - snprintf(spare_buff, sizeof(spare_buff), - "FAILURE PREDICTION THRESHOLD EXCEEDED: ascq=0x%x", ascq); - return spare_buff; - } else if (SCSI_ASC_WARNING == asc) { - if (ascq < (sizeof(strs_for_asc_b) / sizeof(strs_for_asc_b[0]))) { - rp = strs_for_asc_b[ascq]; - if (strlen(rp) > 0) - return rp; - } - snprintf(spare_buff, sizeof(spare_buff), "WARNING: ascq=0x%x", ascq); - return spare_buff; - } - return NULL; /* not a IE additional sense code */ -} - - -/* This is not documented in t10.org, page 0x80 is vendor specific */ -/* Some IBM disks do an offline read-scan when they get this command. */ -int scsiSmartIBMOfflineTest(int device) -{ - UINT8 tBuf[256]; - - memset(tBuf, 0, sizeof(tBuf)); - /* Build SMART Off-line Immediate Diag Header */ - tBuf[0] = 0x80; /* Page Code */ - tBuf[1] = 0x00; /* Reserved */ - tBuf[2] = 0x00; /* Page Length MSB */ - tBuf[3] = 0x04; /* Page Length LSB */ - tBuf[4] = 0x03; /* SMART Revision */ - tBuf[5] = 0x00; /* Reserved */ - tBuf[6] = 0x00; /* Off-line Immediate Time MSB */ - tBuf[7] = 0x00; /* Off-line Immediate Time LSB */ - return scsiSendDiagnostic(device, SCSI_DIAG_NO_SELF_TEST, tBuf, 8); -} - -int scsiSmartDefaultSelfTest(int device) -{ - return scsiSendDiagnostic(device, SCSI_DIAG_DEF_SELF_TEST, NULL, 0); -} - -int scsiSmartShortSelfTest(int device) -{ - return scsiSendDiagnostic(device, SCSI_DIAG_BG_SHORT_SELF_TEST, NULL, 0); -} - -int scsiSmartExtendSelfTest(int device) -{ - return scsiSendDiagnostic(device, SCSI_DIAG_BG_EXTENDED_SELF_TEST, - NULL, 0); -} - -int scsiSmartShortCapSelfTest(int device) -{ - return scsiSendDiagnostic(device, SCSI_DIAG_FG_SHORT_SELF_TEST, NULL, 0); -} - -int scsiSmartExtendCapSelfTest(int device) -{ - return scsiSendDiagnostic(device, SCSI_DIAG_FG_EXTENDED_SELF_TEST, - NULL, 0); -} - -int scsiSmartSelfTestAbort(int device) -{ - return scsiSendDiagnostic(device, SCSI_DIAG_ABORT_SELF_TEST, NULL, 0); -} - -int scsiFetchExtendedSelfTestTime(int device, int * durationSec) -{ - int err, offset, res; - UINT8 buff[64]; - int modese_10 = 0; - - memset(buff, 0, sizeof(buff)); - if ((err = scsiModeSense(device, CONTROL_MODE_PAGE_PARAMETERS, - 0, buff, sizeof(buff)))) { - if (2 == err) { /* opcode no good so try 10 byte mode sense */ - err = scsiModeSense10(device, CONTROL_MODE_PAGE_PARAMETERS, - 0, buff, sizeof(buff)); - if (0 == err) - modese_10 = 1; - else - return err; - } else - return err; - } - offset = scsiModePageOffset(buff, sizeof(buff), modese_10); - if (offset < 0) - return -EINVAL; - if (buff[offset + 1] >= 0xa) { - res = (buff[offset + 10] << 8) | buff[offset + 11]; - *durationSec = res; - return 0; - } - else - return -EINVAL; -} - -void scsiDecodeErrCounterPage(unsigned char * resp, - struct scsiErrorCounter *ecp) -{ - int k, j, num, pl, pc; - unsigned char * ucp; - unsigned char * xp; - unsigned long long * ullp; - - memset(ecp, 0, sizeof(*ecp)); - num = (resp[2] << 8) | resp[3]; - ucp = &resp[0] + 4; - while (num > 3) { - pc = (ucp[0] << 8) | ucp[1]; - pl = ucp[3] + 4; - switch (pc) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - ecp->gotPC[pc] = 1; - ullp = &ecp->counter[pc]; - break; - default: - ecp->gotExtraPC = 1; - ullp = &ecp->counter[7]; - break; - } - k = pl - 4; - xp = ucp + 4; - if (k > sizeof(*ullp)) { - xp += (k - sizeof(*ullp)); - k = sizeof(*ullp); - } - *ullp = 0; - for (j = 0; j < k; ++j) { - if (j > 0) - *ullp <<= 8; - *ullp |= xp[j]; - } - num -= pl; - ucp += pl; - } -} - -void scsiDecodeNonMediumErrPage(unsigned char *resp, - struct scsiNonMediumError *nmep) -{ - int k, j, num, pl, pc, szof; - unsigned char * ucp; - unsigned char * xp; - - memset(nmep, 0, sizeof(*nmep)); - num = (resp[2] << 8) | resp[3]; - ucp = &resp[0] + 4; - szof = sizeof(nmep->counterPC0); - while (num > 3) { - pc = (ucp[0] << 8) | ucp[1]; - pl = ucp[3] + 4; - switch (pc) { - case 0: - nmep->gotPC0 = 1; - k = pl - 4; - xp = ucp + 4; - if (k > szof) { - xp += (k - szof); - k = szof; - } - nmep->counterPC0 = 0; - for (j = 0; j < k; ++j) { - if (j > 0) - nmep->counterPC0 <<= 8; - nmep->counterPC0 |= xp[j]; - } - break; - default: - nmep->gotExtraPC = 1; - break; - } - num -= pl; - ucp += pl; - } -} diff --git a/sm5/scsicmds.h b/sm5/scsicmds.h deleted file mode 100644 index d8420a850..000000000 --- a/sm5/scsicmds.h +++ /dev/null @@ -1,299 +0,0 @@ -/* - * scsicmds.h - * - * Home page of code is: http://smartmontools.sourceforge.net - * - * Copyright (C) 2002-3 Bruce Allen <smartmontools-support@lists.sourceforge.net> - * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org> - * - * 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 Software Foundation; either version 2, or (at your option) - * any later version. - * - * You should have received a copy of the GNU General Public License - * (for example COPYING); if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * This code was originally developed as a Senior Thesis by Michael Cornwell - * at the Concurrent Systems Laboratory (now part of the Storage Systems - * Research Center), Jack Baskin School of Engineering, University of - * California, Santa Cruz. http://ssrc.soe.ucsc.edu/ - * - * N.B. What was formerly known as "SMART" are now called "informational - * exceptions" in recent t10.org drafts (i.e. recent SCSI). - * - */ - - -#ifndef SCSICMDS_H_ -#define SCSICMDS_H_ - -#ifndef SCSICMDS_H_CVSID -#define SCSICMDS_H_CVSID "$Id: scsicmds.h,v 1.27 2003/04/29 16:01:11 makisara Exp $\n" -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <getopt.h> -#include <unistd.h> -#include <errno.h> -#include <sys/ioctl.h> - -/* #define SCSI_DEBUG 1 */ /* Comment out to disable command debugging */ - -/* Following conditional defines bypass inclusion of scsi/scsi.h and - * scsi/scsi_ioctl.h . Issue will be resolved later ... */ -#ifndef TEST_UNIT_READY -#define TEST_UNIT_READY 0x0 -#endif -#ifndef LOG_SENSE -#define LOG_SENSE 0x4d -#endif -#ifndef MODE_SENSE -#define MODE_SENSE 0x1a -#endif -#ifndef MODE_SENSE_10 -#define MODE_SENSE_10 0x5a -#endif -#ifndef MODE_SELECT -#define MODE_SELECT 0x15 -#endif -#ifndef MODE_SELECT_10 -#define MODE_SELECT_10 0x55 -#endif -#ifndef INQUIRY -#define INQUIRY 0x12 -#endif -#ifndef REQUEST_SENSE -#define REQUEST_SENSE 0x03 -#endif -#ifndef RECEIVE_DIAGNOSTIC -#define RECEIVE_DIAGNOSTIC 0x1c -#endif -#ifndef SEND_DIAGNOSTIC -#define SEND_DIAGNOSTIC 0x1d -#endif - -typedef unsigned char UINT8; -typedef char INT8; -typedef unsigned int UINT32; -typedef int INT32; - -#define DXFER_NONE 0 -#define DXFER_FROM_DEVICE 1 -#define DXFER_TO_DEVICE 2 - -struct scsi_cmnd_io -{ - UINT8 * cmnd; - size_t cmnd_len; - int dxfer_dir; /* DXFER_NONE, DXFER_FROM_DEVICE, or DXFER_TO_DEVICE */ - UINT8 * dxferp; - size_t dxfer_len; - UINT8 * sensep; /* ptr to sense buffer when CHECK CONDITION status */ - size_t max_sense_len; - unsigned timeout; /* in seconds, 0-> default timeout (60 seconds?) */ - size_t resp_sense_len; /* output: sense buffer length */ - UINT8 scsi_status; /* output: 0->ok, 2->CHECK CONDITION, etc ... */ - int resid; /* Number of bytes requested to be transferred less */ - /* actual number transferred (0 if not supported) */ -}; - -struct scsi_sense_disect { - UINT8 error_code; - UINT8 sense_key; - UINT8 asc; - UINT8 ascq; -}; - -/* Useful data from Informational Exception Control mode page (0x1c) */ -#define SCSI_IECMP_RAW_LEN 64 -struct scsi_iec_mode_page { - UINT8 requestedCurrent; - UINT8 gotCurrent; - UINT8 requestedChangeable; - UINT8 gotChangeable; - UINT8 modese_10; - UINT8 raw_curr[SCSI_IECMP_RAW_LEN]; - UINT8 raw_chg[SCSI_IECMP_RAW_LEN]; -}; - -/* Carrier for Error counter log pages (e.g. read, write, verify ...) */ -struct scsiErrorCounter { - UINT8 gotPC[7]; - UINT8 gotExtraPC; - unsigned long long counter[8]; -}; - -/* Carrier for Non-medium error log page */ -struct scsiNonMediumError { - UINT8 gotPC0; - UINT8 gotExtraPC; - unsigned long long counterPC0; -}; - -/* SCSI Peripheral types (of interest) */ -#define SCSI_PT_DIRECT_ACCESS 0x0 -#define SCSI_PT_SEQUENTIAL_ACCESS 0x1 -#define SCSI_PT_CDROM 0x5 -#define SCSI_PT_MEDIUM_CHANGER 0x8 -#define SCSI_PT_ENCLOSURE 0xd - -/* ANSI SCSI-3 Log Pages retrieved by LOG SENSE. */ -#define SUPPORTED_LOG_PAGES 0x00 -#define BUFFER_OVERRUN_PAGE 0x01 -#define WRITE_ERROR_COUNTER_PAGE 0x02 -#define READ_ERROR_COUNTER_PAGE 0x03 -#define READ_REVERSE_ERROR_COUNTER_PAGE 0x04 -#define VERIFY_ERROR_COUNTER_PAGE 0x05 -#define NON_MEDIUM_ERROR_PAGE 0x06 -#define LAST_N_ERROR_PAGE 0x07 -#define FORMAT_STATUS_PAGE 0x08 -#define TEMPERATURE_PAGE 0x0d -#define STARTSTOP_CYCLE_COUNTER_PAGE 0x0e -#define APPLICATION_CLIENT_PAGE 0x0f -#define SELFTEST_RESULTS_PAGE 0x10 -#define IE_LOG_PAGE 0x2f - -/* See the SSC-2 document at www.t10.org . Earler note: From IBM -Documentation, see http://www.storage.ibm.com/techsup/hddtech/prodspecs.htm */ -#define TAPE_ALERTS_PAGE 0x2e - -/* ANSI SCSI-3 Mode Pages */ -#define VENDOR_UNIQUE_PARAMETERS 0x00 -#define READ_WRITE_ERROR_RECOVERY_PARAMETERS 0x01 -#define DISCONNECT_RECONNECT_PARAMETERS 0x02 -#define FORMAT_DEVICE_PARAMETERS 0x03 -#define RIGID_DISK_DRIVE_GEOMETRY_PARAMETERS 0x04 -#define FLEXIBLE_DISK_PARAMETERS 0x05 -#define VERIFY_ERROR_RECOVERY_PARAMETERS 0x07 -#define CACHING_PARAMETERS 0x08 -#define PERIPHERAL_DEVICE 0x09 -#define XOR_CONTROL_MODE_PARAMETERS 0x10 -#define CONTROL_MODE_PAGE_PARAMETERS 0x0a -#define MEDIUM_TYPES_SUPPORTED 0x0b -#define NOTCH_PARAMETERS 0x0c -#define POWER_CONDITION_PARAMETERS 0x0d -#define CD_DEVICE_PARAMETERS 0x0d -#define CD_AUDIO_CONTROL_PAGE 0x0e -#define DATA_COMPRESSION_PARAMETERS 0x0f -#define MEDIUM_PARTITION_MODE_PARAMTERES_1 0x11 -#define MEDIUM_PARTITION_MODE_PARAMTERES_2 0x12 -#define MEDIUM_PARTITION_MODE_PARAMTERES_3 0x13 -#define MEDIUM_PARTITION_MODE_PARAMTERES_4 0x14 -#define ENCLOSURE_SERVICES_MANAGEMENT 0x14 -#define LUN_CONTROL 0x18 -#define PORT_CONTROL 0x19 -#define POWER_CONTROL 0x1a -#define LUN_MAPPING_PAGE 0x1b -#define INFORMATIONAL_EXCEPTIONS_CONTROL 0x1c -#define FAULT_FAILURE_REPORTING_PAGE 0x1c -#define ELEMENT_ADDRESS_ASSIGNMENT 0x1d -#define TIMEOUT_AND_PROTECT_PARAMETERS 0x1d -#define TRANSPORT_GEOMETRY_PARAMETERS 0x1e -#define DEVICE_CAPABILITIES 0x1f -#define CD_CAPABILITIES_AND_MECHANISM_STATUS 0x2a - -#define ALL_PARAMETERS 0x3f - -/* defines for useful SCSI Status codes */ -#define SCSI_STATUS_CHECK_CONDITION 0x2 - -/* defines for useful Sense Key codes */ -#define SCSI_SK_NOT_READY 0x2 -#define SCSI_SK_ILLEGAL_REQUEST 0x5 -#define SCSI_SK_UNIT_ATTENTION 0x6 - -/* defines for useful Additional Sense Codes (ASCs) */ -#define SCSI_ASC_UNKNOWN_OPCODE 0x20 -#define SCSI_ASC_UNKNOWN_FIELD 0x24 -#define SCSI_ASC_UNKNOWN_PARAM 0x26 -#define SCSI_ASC_WARNING 0xb -#define SCSI_ASC_IMPENDING_FAILURE 0x5d - - -/* defines for functioncode parameter in SENDDIAGNOSTIC function */ - -#define SCSI_DIAG_NO_SELF_TEST 0x00 -#define SCSI_DIAG_DEF_SELF_TEST 0xff -#define SCSI_DIAG_BG_SHORT_SELF_TEST 0x01 -#define SCSI_DIAG_BG_EXTENDED_SELF_TEST 0x02 -#define SCSI_DIAG_FG_SHORT_SELF_TEST 0x05 -#define SCSI_DIAG_FG_EXTENDED_SELF_TEST 0x06 -#define SCSI_DIAG_ABORT_SELF_TEST 0x04 - - - -#define LOGPAGEHDRSIZE 4 - -void scsi_do_sense_disect(const struct scsi_cmnd_io * in, - struct scsi_sense_disect * out); - -const char * scsiErrString(int scsiErr); - -/* STANDARD SCSI Commands */ -int scsiTestUnitReady(int device); - -int scsiStdInquiry(int device, UINT8 *pBuf, int bufLen); - -int scsiInquiryVpd(int device, int vpd_page, UINT8 *pBuf, int bufLen); - -int scsiLogSense(int device, int pagenum, UINT8 *pBuf, int bufLen); - -int scsiModeSense(int device, int pagenum, int pc, UINT8 *pBuf, int bufLen); - -int scsiModeSelect(int device, int pagenum, int sp, UINT8 *pBuf, int bufLen); - -int scsiModeSense10(int device, int pagenum, int pc, UINT8 *pBuf, int bufLen); - -int scsiModeSelect10(int device, int pagenum, int sp, UINT8 *pBuf, int bufLen); - -int scsiRequestSense(int device, struct scsi_sense_disect * sense_info); - -int scsiSendDiagnostic(int device, int functioncode, UINT8 *pBuf, int bufLen); - -int scsiReceiveSiagnostic(int device, int pcv, int pagenum, UINT8 *pBuf, - int bufLen); -/* SMART specific commands */ - -#define CHECK_SMART_BY_LGPG_2F 0x01 -#define CHECK_SMART_BY_REQSENSE 0x00 - -int scsiCheckIE(int device, int method, int hasTempLogPage, - UINT8 *asc, UINT8 *ascq, UINT8 *currenttemp); - -int scsiFetchIECmpage(int device, struct scsi_iec_mode_page *iecp); -int scsi_IsExceptionControlEnabled(const struct scsi_iec_mode_page *iecp); -int scsi_IsWarningEnabled(const struct scsi_iec_mode_page *iecp); -int scsiSetExceptionControlAndWarning(int device, int enabled, - const struct scsi_iec_mode_page *iecp); -int scsiDecodeIEModePage(const struct scsi_iec_mode_page *iecp, - UINT8 *byte_2p, UINT8 *mrie_p, unsigned int *interval_timer_p, - unsigned int *report_count_p); -void scsiDecodeErrCounterPage(unsigned char * resp, - struct scsiErrorCounter *ecp); -void scsiDecodeNonMediumErrPage(unsigned char * resp, - struct scsiNonMediumError *nmep); -int scsiFetchExtendedSelfTestTime(int device, int * durationSec); - -/* T10 Standard IE Additional Sense Code strings taken from t10.org */ - -const char* scsiGetIEString(UINT8 asc, UINT8 ascq); -int scsiGetTemp(int device, UINT8 *currenttemp, UINT8 *triptemp); - - -int scsiSmartIBMOfflineTest(int device); - -int scsiSmartDefaultSelfTest(int device); -int scsiSmartShortSelfTest(int device); -int scsiSmartExtendSelfTest(int device); -int scsiSmartShortCapSelfTest(int device); -int scsiSmartExtendCapSelfTest(int device); -int scsiSmartSelfTestAbort(int device); - -const char * scsiTapeAlertsTapeDevice(unsigned short code); -const char * scsiTapeAlertsChangerDevice(unsigned short code); -#endif - diff --git a/sm5/scsiprint.c b/sm5/scsiprint.c deleted file mode 100644 index b14659357..000000000 --- a/sm5/scsiprint.c +++ /dev/null @@ -1,707 +0,0 @@ -/* - * scsiprint.c - * - * Home page of code is: http://smartmontools.sourceforge.net - * - * Copyright (C) 2002-3 Bruce Allen <smartmontools-support@lists.sourceforge.net> - * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org> - * - * Additional SCSI work: - * Copyright (C) 2003 Douglas Gilbert <dougg@torque.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 - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * You should have received a copy of the GNU General Public License - * (for example COPYING); if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * This code was originally developed as a Senior Thesis by Michael Cornwell - * at the Concurrent Systems Laboratory (now part of the Storage Systems - * Research Center), Jack Baskin School of Engineering, University of - * California, Santa Cruz. http://ssrc.soe.ucsc.edu/ - * - */ - - -#include <stdio.h> -#include <unistd.h> -#include <string.h> -#include <fcntl.h> -#include <errno.h> - -#include "extern.h" -#include "scsicmds.h" -#include "scsiprint.h" -#include "smartctl.h" -#include "utility.h" - -#define GBUF_SIZE 65535 - -const char* scsiprint_c_cvsid="$Id: scsiprint.c,v 1.42 2003/05/01 08:50:17 dpgilbert Exp $" -EXTERN_H_CVSID SCSICMDS_H_CVSID SCSIPRINT_H_CVSID SMARTCTL_H_CVSID UTILITY_H_CVSID; - -// control block which points to external global control variables -extern smartmonctrl *con; - -UINT8 gBuf[GBUF_SIZE]; -#define LOG_RESP_LEN 252 - -/* Log pages supported */ -static int gSmartPage = 0; -static int gTempPage = 0; -static int gSelfTestPage = 0; -static int gStartStopPage = 0; -static int gTapeAlertsPage = 0; - - -static void scsiGetSupportedLogPages(int device) -{ - int i, err; - - if ((err = scsiLogSense(device, SUPPORTED_LOG_PAGES, gBuf, - LOG_RESP_LEN))) { - if (con->reportscsiioctl > 0) - pout("Log Sense for supported pages failed [%s]\n", - scsiErrString(err)); - return; - } - - for (i = 4; i < gBuf[3] + LOGPAGEHDRSIZE; i++) { - switch (gBuf[i]) - { - case TEMPERATURE_PAGE: - gTempPage = 1; - break; - case STARTSTOP_CYCLE_COUNTER_PAGE: - gStartStopPage = 1; - break; - case SELFTEST_RESULTS_PAGE: - gSelfTestPage = 1; - break; - case IE_LOG_PAGE: - gSmartPage = 1; - break; - case TAPE_ALERTS_PAGE: - gTapeAlertsPage = 1; - break; - default: - break; - } - } -} - -void scsiGetSmartData(int device) -{ - UINT8 asc; - UINT8 ascq; - UINT8 currenttemp = 0; - const char * cp; - int err; - - QUIETON(con); - if ((err = scsiCheckIE(device, gSmartPage, gTempPage, - &asc, &ascq, ¤ttemp))) { - /* error message already announced */ - QUIETOFF(con); - return; - } - QUIETOFF(con); - cp = scsiGetIEString(asc, ascq); - if (cp) { - QUIETON(con); - pout("SMART Sense: %s [asc=%x,ascq=%x]\n", cp, asc, ascq); - QUIETOFF(con); - } else - pout("SMART Sense: Ok!\n"); - - if (currenttemp && !gTempPage) { - if (255 != currenttemp) - pout("Current Drive Temperature: %d C\n", currenttemp); - else - pout("Current Drive Temperature: <not available>\n"); - } -} - - -// Returns number of logged errors or zero if none or -1 if fetching -// TapeAlerts fails -static int scsiGetTapeAlertsData(int device, int peripheral_type) -{ - unsigned short pagelength; - unsigned short parametercode; - int i, err; - int failures = 0; - - QUIETON(con); - if ((err = scsiLogSense(device, TAPE_ALERTS_PAGE, gBuf, LOG_RESP_LEN))) { - pout("scsiGetTapesAlertData Failed [%s]\n", scsiErrString(err)); - QUIETOFF(con); - return -1; - } - if (gBuf[0] != 0x2e) { - pout("TapeAlerts Log Sense Failed\n"); - QUIETOFF(con); - return -1; - } - pagelength = (unsigned short) gBuf[2] << 8 | gBuf[3]; - - for (i = 4; i < pagelength; i += 5) { - parametercode = (unsigned short) gBuf[i] << 8 | gBuf[i+1]; - - if (gBuf[i + 4]) { - if (!failures) - pout("TapeAlert Errors:\n"); - pout("[0x%02x] %s\n", parametercode, - SCSI_PT_MEDIUM_CHANGER == peripheral_type ? - scsiTapeAlertsChangerDevice(parametercode) : - scsiTapeAlertsTapeDevice(parametercode)); - failures += 1; - } - } - QUIETOFF(con); - - if (! failures) - pout("TapeAlert: Ok!\n"); - - return failures; -} - -void scsiGetStartStopData(int device) -{ - UINT32 currentStartStop; - UINT32 recommendedStartStop; - int err, len, k; - char str[6]; - - if ((err = scsiLogSense(device, STARTSTOP_CYCLE_COUNTER_PAGE, gBuf, - LOG_RESP_LEN))) { - QUIETON(con); - pout("scsiGetStartStopData Failed [%s]\n", scsiErrString(err)); - QUIETOFF(con); - return; - } - if (gBuf[0] != STARTSTOP_CYCLE_COUNTER_PAGE) { - QUIETON(con); - pout("StartStop Log Sense Failed, page mismatch\n"); - QUIETOFF(con); - return; - } - len = ((gBuf[2] << 8) | gBuf[3]) + 4; - if (len > 13) { - for (k = 0; k < 2; ++k) - str[k] = gBuf[12 + k]; - str[k] = '\0'; - pout("Manufactured in week %s of year ", str); - for (k = 0; k < 4; ++k) - str[k] = gBuf[8 + k]; - str[k] = '\0'; - pout("%s\n", str); - } - if (len > 39) { - recommendedStartStop = (gBuf[28] << 24) | (gBuf[29] << 16) | - (gBuf[30] << 8) | gBuf[31]; - currentStartStop = (gBuf[36] << 24) | (gBuf[37] << 16) | - (gBuf[38] << 8) | gBuf[39]; - pout("Current start stop count: %u times\n", currentStartStop); - pout("Recommended start stop count: %u times\n", - recommendedStartStop); - } -} - -static void scsiPrintErrorCounterLog(int device) -{ - struct scsiErrorCounter errCounterArr[3]; - struct scsiErrorCounter * ecp; - struct scsiNonMediumError nme; - int found[3] = {0, 0, 0}; - const char * pageNames[3] = {"read: ", "write: ", "verify: "}; - int k; - double processed_gb; - - if (0 == scsiLogSense(device, READ_ERROR_COUNTER_PAGE, gBuf, - LOG_RESP_LEN)) { - scsiDecodeErrCounterPage(gBuf, &errCounterArr[0]); - found[0] = 1; - } - if (0 == scsiLogSense(device, WRITE_ERROR_COUNTER_PAGE, gBuf, - LOG_RESP_LEN)) { - scsiDecodeErrCounterPage(gBuf, &errCounterArr[1]); - found[1] = 1; - } - if (0 == scsiLogSense(device, VERIFY_ERROR_COUNTER_PAGE, gBuf, - LOG_RESP_LEN)) { - scsiDecodeErrCounterPage(gBuf, &errCounterArr[2]); - ecp = &errCounterArr[2]; - for (k = 0; k < 7; ++k) { - if (ecp->gotPC[k] && ecp->counter[k]) { - found[2] = 1; - break; - } - } - } - if (found[0] || found[1] || found[2]) { - pout("\nError counter log:\n"); - pout(" Errors Corrected Total Total " - "Correction Gigabytes Total\n"); - pout(" delay: [rereads/ errors " - "algorithm processed uncorrected\n"); - pout(" minor | major rewrites] corrected " - "invocations [10^9 bytes] errors\n"); - for (k = 0; k < 3; ++k) { - if (! found[k]) - continue; - ecp = &errCounterArr[k]; - pout("%s%8llu %8llu %8llu %8llu %8llu", - pageNames[k], ecp->counter[0], ecp->counter[1], - ecp->counter[2], ecp->counter[3], ecp->counter[4]); - processed_gb = ecp->counter[5] / 1000000000.0; - pout(" %12.3f %8llu\n", processed_gb, ecp->counter[6]); - } - } - else - pout("\nNo Error counter log to report\n"); - if (0 == scsiLogSense(device, NON_MEDIUM_ERROR_PAGE, gBuf, - LOG_RESP_LEN)) { - scsiDecodeNonMediumErrPage(gBuf, &nme); - if (nme.gotPC0) - pout("\nNon-medium error count: %8llu\n", nme.counterPC0); - } -} - -const char * self_test_code[] = { - "Default ", - "Background short", - "Background long ", - "Reserved(3) ", - "Abort background", - "Foreground short", - "Foreground long ", - "Reserved(7) " -}; - -const char * self_test_result[] = { - "Completed ", - "Interrupted ('-X' switch)", - "Interrupted (bus reset ?)", - "Unknown error, incomplete", - "Completed, segment failed", - "Failed in first segment ", - "Failed in second segment ", - "Failed in segment --> ", - "Reserved(8) ", - "Reserved(9) ", - "Reserved(10) ", - "Reserved(11) ", - "Reserved(12) ", - "Reserved(13) ", - "Reserved(14) ", - "Self test in progress ..." -}; - -// See Working Draft SCSI Primary Commands - 3 (SPC-3) pages 231-233 -// T10/1416-D Rev 10 -static int scsiPrintSelfTest(int device) -{ - int num, k, n, res, err, durationSec; - int noheader = 1; - UINT8 * ucp; - unsigned long long ull=0; - - if ((err = scsiLogSense(device, SELFTEST_RESULTS_PAGE, gBuf, - LOG_RESP_LEN))) { - QUIETON(con); - pout("scsiPrintSelfTest Failed [%s]\n", scsiErrString(err)); - QUIETOFF(con); - return 1; - } - if (gBuf[0] != SELFTEST_RESULTS_PAGE) { - QUIETON(con); - pout("Self-test Log Sense Failed, page mismatch\n"); - QUIETOFF(con); - return 1; - } - // compute page length - num = (gBuf[2] << 8) + gBuf[3]; - // Log sense page length 0x190 bytes - if (num != 0x190) { - QUIETON(con); - pout("Self-test Log Sense length is 0x%x not 0x190 bytes\n",num); - QUIETOFF(con); - return 1; - } - // loop through the twenty possible entries - for (k = 0, ucp = gBuf + 4; k < 20; ++k, ucp += 20 ) { - int i; - - // timestamp in power-on hours (or zero if test in progress) - n = (ucp[6] << 8) | ucp[7]; - - // The spec says "all 20 bytes will be zero if no test" but - // DG has found otherwise. So this is a heuristic. - if ((0 == n) && (0 == ucp[4])) - break; - - // only print header if needed - if (noheader) { - pout("\nSMART Self-test log\n"); - pout("Num Test Status segment " - "LifeTime LBA_first_err [SK ASC ASQ]\n"); - pout(" Description number " - "(hours)\n"); - noheader=0; - } - - // print parameter code (test number) & self-test code text - pout("#%2d %s", (ucp[0] << 8) | ucp[1], - self_test_code[(ucp[4] >> 5) & 0x7]); - - // self-test result - res = ucp[4] & 0xf; - pout(" %s", self_test_result[res]); - - // self-test number identifies test that failed and consists - // of either the number of the segment that failed during - // the test, or the number of the test that failed and the - // number of the segment in which the test was run, using a - // vendor-specific method of putting both numbers into a - // single byte. - if (ucp[5]) - pout(" %3d", (int)ucp[5]); - else - pout(" -"); - - // print time that the self-test was completed - if (n==0 && res==0xf) - // self-test in progress - pout(" NOW"); - else - pout(" %5d", n); - - // construct 8-byte integer address of first failure - for (i = 0; i < 8; i++) { - ull <<= 8; - ull |= ucp[i+8]; - } - // print Address of First Failure, if sensible - if ((0xffffffffffffffffULL != ull) && (res > 0) && ( res < 0xf)) - pout(" 0x%16llx", ull); - else - pout(" -"); - - // if sense key nonzero, then print it, along with - // additional sense code and additional sense code qualifier - if (ucp[16] & 0xf) - pout(" [0x%x 0x%x 0x%x]\n", ucp[16] & 0xf, ucp[17], ucp[18]); - else - pout(" [- - -]\n"); - } - - // if header never printed, then there was no output - if (noheader) - pout("No self-tests have been logged\n"); - else - pout("\n"); - if ((0 == scsiFetchExtendedSelfTestTime(device, &durationSec)) && - (durationSec > 0)) - pout("Long (extended) Self Test duration: %d seconds " - "[%.1f minutes]\n", durationSec, durationSec / 60.0); - return 0; -} - -/* Returns 0 on success */ -static int scsiGetDriveInfo(int device, UINT8 * peripheral_type, int all) -{ - char manufacturer[9]; - char product[17]; - char revision[5]; - char timedatetz[64]; - struct scsi_iec_mode_page iec; - int err, len; - int is_tape = 0; - - memset(gBuf, 0, 36); - if ((err = scsiStdInquiry(device, gBuf, 36))) { - QUIETON(con); - pout("Standard Inquiry failed [%s]\n", scsiErrString(err)); - QUIETOFF(con); - return 1; - } - len = gBuf[4] + 5; - if (peripheral_type) - *peripheral_type = gBuf[0] & 0x1f; - if (!all) - return 0; - - if (len >= 36) { - memset(manufacturer, 0, sizeof(manufacturer)); - strncpy(manufacturer, &gBuf[8], 8); - - memset(product, 0, sizeof(product)); - strncpy(product, &gBuf[16], 16); - - memset(revision, 0, sizeof(revision)); - strncpy(revision, &gBuf[32], 4); - pout("Device: %s %s Version: %s\n", manufacturer, product, revision); - if (0 == scsiInquiryVpd(device, 0x80, gBuf, 64)) { - /* should use VPD page 0x83 and fall back to this page (0x80) - * if 0x83 not supported. NAA requires a lot of decoding code */ - len = gBuf[3]; - gBuf[4 + len] = '\0'; - pout("Serial number: %s\n", &gBuf[4]); - } - } else { - QUIETON(con); - pout("Short INQUIRY response, skip product id\n"); - QUIETOFF(con); - } - - // print current time and date and timezone - dateandtimezone(timedatetz); - pout("Local Time is: %s\n", timedatetz); - - if ((SCSI_PT_SEQUENTIAL_ACCESS == *peripheral_type) || - (SCSI_PT_MEDIUM_CHANGER == *peripheral_type)) - is_tape = 1; - // See if unit accepts SCSI commmands from us - if ((err = scsiTestUnitReady(device))) { - if (1 == err) { - QUIETON(con); - pout("device is NOT READY (media absent, spun down, etc)\n"); - QUIETOFF(con); - } else { - QUIETON(con); - pout("device Test Unit Ready [%s]\n", scsiErrString(err)); - QUIETOFF(con); - } - return 0; - } - - if ((err = scsiFetchIECmpage(device, &iec))) { - if (!is_tape) { - QUIETON(con); - pout("Device does not support SMART [%s]\n", - scsiErrString(err)); - QUIETOFF(con); - } - return 0; - } - if (!is_tape) - pout("Device supports SMART and is %s\n", - (scsi_IsExceptionControlEnabled(&iec)) ? "Enabled" : "Disabled"); - pout("%s\n", (scsi_IsWarningEnabled(&iec)) ? - "Temperature Warning Enabled" : - "Temperature Warning Disabled or Not Supported"); - return 0; -} - -static int scsiSmartEnable(int device) -{ - struct scsi_iec_mode_page iec; - int err; - - if ((err = scsiFetchIECmpage(device, &iec))) { - QUIETON(con); - pout("unable to fetch IEC (SMART) mode page [%s]\n", - scsiErrString(err)); - QUIETOFF(con); - return 1; - } - if ((err = scsiSetExceptionControlAndWarning(device, 1, &iec))) { - QUIETON(con); - pout("unable to enable Exception control and warning [%s]\n", - scsiErrString(err)); - QUIETOFF(con); - return 1; - } - /* Need to refetch 'iec' since could be modified by previous call */ - if ((err = scsiFetchIECmpage(device, &iec))) { - pout("unable to fetch IEC (SMART) mode page [%s]\n", - scsiErrString(err)); - return 1; - } - pout("Informational Exceptions (SMART) %s\n", - scsi_IsExceptionControlEnabled(&iec) ? "enabled" : "disabled"); - pout("Temperature warning %s\n", - scsi_IsWarningEnabled(&iec) ? "enabled" : "disabled"); - return 0; -} - -static int scsiSmartDisable(int device) -{ - struct scsi_iec_mode_page iec; - int err; - - if ((err = scsiFetchIECmpage(device, &iec))) { - QUIETON(con); - pout("unable to fetch IEC (SMART) mode page [%s]\n", - scsiErrString(err)); - QUIETOFF(con); - return 1; - } - if ((err = scsiSetExceptionControlAndWarning(device, 0, &iec))) { - QUIETON(con); - pout("unable to disable Exception control and warning [%s]\n", - scsiErrString(err)); - QUIETOFF(con); - return 1; - } - /* Need to refetch 'iec' since could be modified by previous call */ - if ((err = scsiFetchIECmpage(device, &iec))) { - pout("unable to fetch IEC (SMART) mode page [%s]\n", - scsiErrString(err)); - return 1; - } - pout("Informational Exceptions (SMART) %s\n", - scsi_IsExceptionControlEnabled(&iec) ? "enabled" : "disabled"); - pout("Temperature warning %s\n", - scsi_IsWarningEnabled(&iec) ? "enabled" : "disabled"); - return 0; -} - -void scsiPrintTemp(int device) -{ - UINT8 temp = 0; - UINT8 trip = 0; - - if (scsiGetTemp(device, &temp, &trip)) - return; - - if (temp) { - if (255 != temp) - pout("Current Drive Temperature: %d C\n", temp); - else - pout("Current Drive Temperature: <not available>\n"); - } - if (trip) - pout("Drive Trip Temperature: %d C\n", trip); -} - -// Compares failure type to policy in effect, and either exits or -// simply returns to the calling routine. -static void failuretest(int type, int returnvalue) -{ - // If this is an error in an "optional" SMART command - if (type == OPTIONAL_CMD) { - if (con->conservative) { - pout("An optional SMART command has failed: exiting.\n" - "To continue, set the tolerance level to something other " - "than 'conservative'\n"); - exit(returnvalue); - } - } - return; -} - - -/* Main entry point used by smartctl command. Return 0 for success */ -int scsiPrintMain(const char *dev_name, int fd) -{ - int checkedSupportedLogPages = 0; - UINT8 peripheral_type = 0; - int returnval=0; - int res; - - if (scsiGetDriveInfo(fd, &peripheral_type, con->driveinfo)) { - pout("Smartctl: SCSI device INQUIRY Failed\n\n"); - failuretest(MANDATORY_CMD, returnval |= FAILID); - } - - if (con->smartenable) { - if (scsiSmartEnable(fd)) - failuretest(MANDATORY_CMD, returnval |= FAILSMART); - } - - if (con->smartdisable) { - if (scsiSmartDisable(fd)) - failuretest(MANDATORY_CMD,returnval |= FAILSMART); - } - - if (con->checksmart) { - scsiGetSupportedLogPages(fd); - checkedSupportedLogPages = 1; - if ((SCSI_PT_SEQUENTIAL_ACCESS == peripheral_type) || - (SCSI_PT_MEDIUM_CHANGER == peripheral_type)) { /* tape device */ - if (gTapeAlertsPage) { - if (con->driveinfo) - pout("TapeAlert Supported\n"); - if (-1 == scsiGetTapeAlertsData(fd, peripheral_type)) - failuretest(OPTIONAL_CMD, returnval |= FAILSMART); - } - else - pout("TapeAlert Not Supported\n"); - if (gTempPage) - scsiPrintTemp(fd); - if (gStartStopPage) - scsiGetStartStopData(fd); - } else { /* disk, cd/dvd, enclosure, etc */ - scsiGetSmartData(fd); - if (gTempPage) - scsiPrintTemp(fd); - if (gStartStopPage) - scsiGetStartStopData(fd); - } - } - if (con->smarterrorlog) - scsiPrintErrorCounterLog(fd); - if (con->smartselftestlog) { - if (! checkedSupportedLogPages) - scsiGetSupportedLogPages(fd); - res = 0; - if (gSelfTestPage) - res = scsiPrintSelfTest(fd); - else { - pout("Warning: device does not support Self Test Logging\n"); - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - } - if (0 != res) - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - } - if (con->smartexeoffimmediate) { - if (scsiSmartDefaultSelfTest(fd)) { - pout( "Default Self Test Failed\n"); - return returnval; - } - pout("Default Self Test Successful\n"); - } - if (con->smartshortcapselftest) { - if (scsiSmartShortCapSelfTest(fd)) { - pout("Short Foreground Self Test Failed\n"); - return returnval; - } - pout("Short Foreground Self Test Successful\n"); - } - if (con->smartshortselftest ) { - if ( scsiSmartShortSelfTest(fd)) { - pout("Short Background Self Test Failed\n"); - return returnval; - } - pout("Short Background Self Test has begun\n"); - pout("Use smartctl -X to abort test\n"); - } - if (con->smartextendselftest) { - if (scsiSmartExtendSelfTest(fd)) { - pout("Extended Background Self Test Failed\n"); - return returnval; - } - pout("Extended Background Self Test has begun\n"); - pout("Use smartctl -X to abort test\n"); - } - if (con->smartextendcapselftest) { - if (scsiSmartExtendCapSelfTest(fd)) { - pout("Extended Foreground Self Test Failed\n"); - return returnval; - } - pout("Extended Foreground Self Test Successful\n"); - } - if (con->smartselftestabort) { - if (scsiSmartSelfTestAbort(fd)) { - pout("Self Test Abort Failed\n"); - return returnval; - } - pout("Self Test returned without error\n"); - } - return returnval; -} diff --git a/sm5/scsiprint.cpp b/sm5/scsiprint.cpp deleted file mode 100644 index 181434ca7..000000000 --- a/sm5/scsiprint.cpp +++ /dev/null @@ -1,707 +0,0 @@ -/* - * scsiprint.c - * - * Home page of code is: http://smartmontools.sourceforge.net - * - * Copyright (C) 2002-3 Bruce Allen <smartmontools-support@lists.sourceforge.net> - * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org> - * - * Additional SCSI work: - * Copyright (C) 2003 Douglas Gilbert <dougg@torque.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 - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * You should have received a copy of the GNU General Public License - * (for example COPYING); if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * This code was originally developed as a Senior Thesis by Michael Cornwell - * at the Concurrent Systems Laboratory (now part of the Storage Systems - * Research Center), Jack Baskin School of Engineering, University of - * California, Santa Cruz. http://ssrc.soe.ucsc.edu/ - * - */ - - -#include <stdio.h> -#include <unistd.h> -#include <string.h> -#include <fcntl.h> -#include <errno.h> - -#include "extern.h" -#include "scsicmds.h" -#include "scsiprint.h" -#include "smartctl.h" -#include "utility.h" - -#define GBUF_SIZE 65535 - -const char* scsiprint_c_cvsid="$Id: scsiprint.cpp,v 1.42 2003/05/01 08:50:17 dpgilbert Exp $" -EXTERN_H_CVSID SCSICMDS_H_CVSID SCSIPRINT_H_CVSID SMARTCTL_H_CVSID UTILITY_H_CVSID; - -// control block which points to external global control variables -extern smartmonctrl *con; - -UINT8 gBuf[GBUF_SIZE]; -#define LOG_RESP_LEN 252 - -/* Log pages supported */ -static int gSmartPage = 0; -static int gTempPage = 0; -static int gSelfTestPage = 0; -static int gStartStopPage = 0; -static int gTapeAlertsPage = 0; - - -static void scsiGetSupportedLogPages(int device) -{ - int i, err; - - if ((err = scsiLogSense(device, SUPPORTED_LOG_PAGES, gBuf, - LOG_RESP_LEN))) { - if (con->reportscsiioctl > 0) - pout("Log Sense for supported pages failed [%s]\n", - scsiErrString(err)); - return; - } - - for (i = 4; i < gBuf[3] + LOGPAGEHDRSIZE; i++) { - switch (gBuf[i]) - { - case TEMPERATURE_PAGE: - gTempPage = 1; - break; - case STARTSTOP_CYCLE_COUNTER_PAGE: - gStartStopPage = 1; - break; - case SELFTEST_RESULTS_PAGE: - gSelfTestPage = 1; - break; - case IE_LOG_PAGE: - gSmartPage = 1; - break; - case TAPE_ALERTS_PAGE: - gTapeAlertsPage = 1; - break; - default: - break; - } - } -} - -void scsiGetSmartData(int device) -{ - UINT8 asc; - UINT8 ascq; - UINT8 currenttemp = 0; - const char * cp; - int err; - - QUIETON(con); - if ((err = scsiCheckIE(device, gSmartPage, gTempPage, - &asc, &ascq, ¤ttemp))) { - /* error message already announced */ - QUIETOFF(con); - return; - } - QUIETOFF(con); - cp = scsiGetIEString(asc, ascq); - if (cp) { - QUIETON(con); - pout("SMART Sense: %s [asc=%x,ascq=%x]\n", cp, asc, ascq); - QUIETOFF(con); - } else - pout("SMART Sense: Ok!\n"); - - if (currenttemp && !gTempPage) { - if (255 != currenttemp) - pout("Current Drive Temperature: %d C\n", currenttemp); - else - pout("Current Drive Temperature: <not available>\n"); - } -} - - -// Returns number of logged errors or zero if none or -1 if fetching -// TapeAlerts fails -static int scsiGetTapeAlertsData(int device, int peripheral_type) -{ - unsigned short pagelength; - unsigned short parametercode; - int i, err; - int failures = 0; - - QUIETON(con); - if ((err = scsiLogSense(device, TAPE_ALERTS_PAGE, gBuf, LOG_RESP_LEN))) { - pout("scsiGetTapesAlertData Failed [%s]\n", scsiErrString(err)); - QUIETOFF(con); - return -1; - } - if (gBuf[0] != 0x2e) { - pout("TapeAlerts Log Sense Failed\n"); - QUIETOFF(con); - return -1; - } - pagelength = (unsigned short) gBuf[2] << 8 | gBuf[3]; - - for (i = 4; i < pagelength; i += 5) { - parametercode = (unsigned short) gBuf[i] << 8 | gBuf[i+1]; - - if (gBuf[i + 4]) { - if (!failures) - pout("TapeAlert Errors:\n"); - pout("[0x%02x] %s\n", parametercode, - SCSI_PT_MEDIUM_CHANGER == peripheral_type ? - scsiTapeAlertsChangerDevice(parametercode) : - scsiTapeAlertsTapeDevice(parametercode)); - failures += 1; - } - } - QUIETOFF(con); - - if (! failures) - pout("TapeAlert: Ok!\n"); - - return failures; -} - -void scsiGetStartStopData(int device) -{ - UINT32 currentStartStop; - UINT32 recommendedStartStop; - int err, len, k; - char str[6]; - - if ((err = scsiLogSense(device, STARTSTOP_CYCLE_COUNTER_PAGE, gBuf, - LOG_RESP_LEN))) { - QUIETON(con); - pout("scsiGetStartStopData Failed [%s]\n", scsiErrString(err)); - QUIETOFF(con); - return; - } - if (gBuf[0] != STARTSTOP_CYCLE_COUNTER_PAGE) { - QUIETON(con); - pout("StartStop Log Sense Failed, page mismatch\n"); - QUIETOFF(con); - return; - } - len = ((gBuf[2] << 8) | gBuf[3]) + 4; - if (len > 13) { - for (k = 0; k < 2; ++k) - str[k] = gBuf[12 + k]; - str[k] = '\0'; - pout("Manufactured in week %s of year ", str); - for (k = 0; k < 4; ++k) - str[k] = gBuf[8 + k]; - str[k] = '\0'; - pout("%s\n", str); - } - if (len > 39) { - recommendedStartStop = (gBuf[28] << 24) | (gBuf[29] << 16) | - (gBuf[30] << 8) | gBuf[31]; - currentStartStop = (gBuf[36] << 24) | (gBuf[37] << 16) | - (gBuf[38] << 8) | gBuf[39]; - pout("Current start stop count: %u times\n", currentStartStop); - pout("Recommended start stop count: %u times\n", - recommendedStartStop); - } -} - -static void scsiPrintErrorCounterLog(int device) -{ - struct scsiErrorCounter errCounterArr[3]; - struct scsiErrorCounter * ecp; - struct scsiNonMediumError nme; - int found[3] = {0, 0, 0}; - const char * pageNames[3] = {"read: ", "write: ", "verify: "}; - int k; - double processed_gb; - - if (0 == scsiLogSense(device, READ_ERROR_COUNTER_PAGE, gBuf, - LOG_RESP_LEN)) { - scsiDecodeErrCounterPage(gBuf, &errCounterArr[0]); - found[0] = 1; - } - if (0 == scsiLogSense(device, WRITE_ERROR_COUNTER_PAGE, gBuf, - LOG_RESP_LEN)) { - scsiDecodeErrCounterPage(gBuf, &errCounterArr[1]); - found[1] = 1; - } - if (0 == scsiLogSense(device, VERIFY_ERROR_COUNTER_PAGE, gBuf, - LOG_RESP_LEN)) { - scsiDecodeErrCounterPage(gBuf, &errCounterArr[2]); - ecp = &errCounterArr[2]; - for (k = 0; k < 7; ++k) { - if (ecp->gotPC[k] && ecp->counter[k]) { - found[2] = 1; - break; - } - } - } - if (found[0] || found[1] || found[2]) { - pout("\nError counter log:\n"); - pout(" Errors Corrected Total Total " - "Correction Gigabytes Total\n"); - pout(" delay: [rereads/ errors " - "algorithm processed uncorrected\n"); - pout(" minor | major rewrites] corrected " - "invocations [10^9 bytes] errors\n"); - for (k = 0; k < 3; ++k) { - if (! found[k]) - continue; - ecp = &errCounterArr[k]; - pout("%s%8llu %8llu %8llu %8llu %8llu", - pageNames[k], ecp->counter[0], ecp->counter[1], - ecp->counter[2], ecp->counter[3], ecp->counter[4]); - processed_gb = ecp->counter[5] / 1000000000.0; - pout(" %12.3f %8llu\n", processed_gb, ecp->counter[6]); - } - } - else - pout("\nNo Error counter log to report\n"); - if (0 == scsiLogSense(device, NON_MEDIUM_ERROR_PAGE, gBuf, - LOG_RESP_LEN)) { - scsiDecodeNonMediumErrPage(gBuf, &nme); - if (nme.gotPC0) - pout("\nNon-medium error count: %8llu\n", nme.counterPC0); - } -} - -const char * self_test_code[] = { - "Default ", - "Background short", - "Background long ", - "Reserved(3) ", - "Abort background", - "Foreground short", - "Foreground long ", - "Reserved(7) " -}; - -const char * self_test_result[] = { - "Completed ", - "Interrupted ('-X' switch)", - "Interrupted (bus reset ?)", - "Unknown error, incomplete", - "Completed, segment failed", - "Failed in first segment ", - "Failed in second segment ", - "Failed in segment --> ", - "Reserved(8) ", - "Reserved(9) ", - "Reserved(10) ", - "Reserved(11) ", - "Reserved(12) ", - "Reserved(13) ", - "Reserved(14) ", - "Self test in progress ..." -}; - -// See Working Draft SCSI Primary Commands - 3 (SPC-3) pages 231-233 -// T10/1416-D Rev 10 -static int scsiPrintSelfTest(int device) -{ - int num, k, n, res, err, durationSec; - int noheader = 1; - UINT8 * ucp; - unsigned long long ull=0; - - if ((err = scsiLogSense(device, SELFTEST_RESULTS_PAGE, gBuf, - LOG_RESP_LEN))) { - QUIETON(con); - pout("scsiPrintSelfTest Failed [%s]\n", scsiErrString(err)); - QUIETOFF(con); - return 1; - } - if (gBuf[0] != SELFTEST_RESULTS_PAGE) { - QUIETON(con); - pout("Self-test Log Sense Failed, page mismatch\n"); - QUIETOFF(con); - return 1; - } - // compute page length - num = (gBuf[2] << 8) + gBuf[3]; - // Log sense page length 0x190 bytes - if (num != 0x190) { - QUIETON(con); - pout("Self-test Log Sense length is 0x%x not 0x190 bytes\n",num); - QUIETOFF(con); - return 1; - } - // loop through the twenty possible entries - for (k = 0, ucp = gBuf + 4; k < 20; ++k, ucp += 20 ) { - int i; - - // timestamp in power-on hours (or zero if test in progress) - n = (ucp[6] << 8) | ucp[7]; - - // The spec says "all 20 bytes will be zero if no test" but - // DG has found otherwise. So this is a heuristic. - if ((0 == n) && (0 == ucp[4])) - break; - - // only print header if needed - if (noheader) { - pout("\nSMART Self-test log\n"); - pout("Num Test Status segment " - "LifeTime LBA_first_err [SK ASC ASQ]\n"); - pout(" Description number " - "(hours)\n"); - noheader=0; - } - - // print parameter code (test number) & self-test code text - pout("#%2d %s", (ucp[0] << 8) | ucp[1], - self_test_code[(ucp[4] >> 5) & 0x7]); - - // self-test result - res = ucp[4] & 0xf; - pout(" %s", self_test_result[res]); - - // self-test number identifies test that failed and consists - // of either the number of the segment that failed during - // the test, or the number of the test that failed and the - // number of the segment in which the test was run, using a - // vendor-specific method of putting both numbers into a - // single byte. - if (ucp[5]) - pout(" %3d", (int)ucp[5]); - else - pout(" -"); - - // print time that the self-test was completed - if (n==0 && res==0xf) - // self-test in progress - pout(" NOW"); - else - pout(" %5d", n); - - // construct 8-byte integer address of first failure - for (i = 0; i < 8; i++) { - ull <<= 8; - ull |= ucp[i+8]; - } - // print Address of First Failure, if sensible - if ((0xffffffffffffffffULL != ull) && (res > 0) && ( res < 0xf)) - pout(" 0x%16llx", ull); - else - pout(" -"); - - // if sense key nonzero, then print it, along with - // additional sense code and additional sense code qualifier - if (ucp[16] & 0xf) - pout(" [0x%x 0x%x 0x%x]\n", ucp[16] & 0xf, ucp[17], ucp[18]); - else - pout(" [- - -]\n"); - } - - // if header never printed, then there was no output - if (noheader) - pout("No self-tests have been logged\n"); - else - pout("\n"); - if ((0 == scsiFetchExtendedSelfTestTime(device, &durationSec)) && - (durationSec > 0)) - pout("Long (extended) Self Test duration: %d seconds " - "[%.1f minutes]\n", durationSec, durationSec / 60.0); - return 0; -} - -/* Returns 0 on success */ -static int scsiGetDriveInfo(int device, UINT8 * peripheral_type, int all) -{ - char manufacturer[9]; - char product[17]; - char revision[5]; - char timedatetz[64]; - struct scsi_iec_mode_page iec; - int err, len; - int is_tape = 0; - - memset(gBuf, 0, 36); - if ((err = scsiStdInquiry(device, gBuf, 36))) { - QUIETON(con); - pout("Standard Inquiry failed [%s]\n", scsiErrString(err)); - QUIETOFF(con); - return 1; - } - len = gBuf[4] + 5; - if (peripheral_type) - *peripheral_type = gBuf[0] & 0x1f; - if (!all) - return 0; - - if (len >= 36) { - memset(manufacturer, 0, sizeof(manufacturer)); - strncpy(manufacturer, &gBuf[8], 8); - - memset(product, 0, sizeof(product)); - strncpy(product, &gBuf[16], 16); - - memset(revision, 0, sizeof(revision)); - strncpy(revision, &gBuf[32], 4); - pout("Device: %s %s Version: %s\n", manufacturer, product, revision); - if (0 == scsiInquiryVpd(device, 0x80, gBuf, 64)) { - /* should use VPD page 0x83 and fall back to this page (0x80) - * if 0x83 not supported. NAA requires a lot of decoding code */ - len = gBuf[3]; - gBuf[4 + len] = '\0'; - pout("Serial number: %s\n", &gBuf[4]); - } - } else { - QUIETON(con); - pout("Short INQUIRY response, skip product id\n"); - QUIETOFF(con); - } - - // print current time and date and timezone - dateandtimezone(timedatetz); - pout("Local Time is: %s\n", timedatetz); - - if ((SCSI_PT_SEQUENTIAL_ACCESS == *peripheral_type) || - (SCSI_PT_MEDIUM_CHANGER == *peripheral_type)) - is_tape = 1; - // See if unit accepts SCSI commmands from us - if ((err = scsiTestUnitReady(device))) { - if (1 == err) { - QUIETON(con); - pout("device is NOT READY (media absent, spun down, etc)\n"); - QUIETOFF(con); - } else { - QUIETON(con); - pout("device Test Unit Ready [%s]\n", scsiErrString(err)); - QUIETOFF(con); - } - return 0; - } - - if ((err = scsiFetchIECmpage(device, &iec))) { - if (!is_tape) { - QUIETON(con); - pout("Device does not support SMART [%s]\n", - scsiErrString(err)); - QUIETOFF(con); - } - return 0; - } - if (!is_tape) - pout("Device supports SMART and is %s\n", - (scsi_IsExceptionControlEnabled(&iec)) ? "Enabled" : "Disabled"); - pout("%s\n", (scsi_IsWarningEnabled(&iec)) ? - "Temperature Warning Enabled" : - "Temperature Warning Disabled or Not Supported"); - return 0; -} - -static int scsiSmartEnable(int device) -{ - struct scsi_iec_mode_page iec; - int err; - - if ((err = scsiFetchIECmpage(device, &iec))) { - QUIETON(con); - pout("unable to fetch IEC (SMART) mode page [%s]\n", - scsiErrString(err)); - QUIETOFF(con); - return 1; - } - if ((err = scsiSetExceptionControlAndWarning(device, 1, &iec))) { - QUIETON(con); - pout("unable to enable Exception control and warning [%s]\n", - scsiErrString(err)); - QUIETOFF(con); - return 1; - } - /* Need to refetch 'iec' since could be modified by previous call */ - if ((err = scsiFetchIECmpage(device, &iec))) { - pout("unable to fetch IEC (SMART) mode page [%s]\n", - scsiErrString(err)); - return 1; - } - pout("Informational Exceptions (SMART) %s\n", - scsi_IsExceptionControlEnabled(&iec) ? "enabled" : "disabled"); - pout("Temperature warning %s\n", - scsi_IsWarningEnabled(&iec) ? "enabled" : "disabled"); - return 0; -} - -static int scsiSmartDisable(int device) -{ - struct scsi_iec_mode_page iec; - int err; - - if ((err = scsiFetchIECmpage(device, &iec))) { - QUIETON(con); - pout("unable to fetch IEC (SMART) mode page [%s]\n", - scsiErrString(err)); - QUIETOFF(con); - return 1; - } - if ((err = scsiSetExceptionControlAndWarning(device, 0, &iec))) { - QUIETON(con); - pout("unable to disable Exception control and warning [%s]\n", - scsiErrString(err)); - QUIETOFF(con); - return 1; - } - /* Need to refetch 'iec' since could be modified by previous call */ - if ((err = scsiFetchIECmpage(device, &iec))) { - pout("unable to fetch IEC (SMART) mode page [%s]\n", - scsiErrString(err)); - return 1; - } - pout("Informational Exceptions (SMART) %s\n", - scsi_IsExceptionControlEnabled(&iec) ? "enabled" : "disabled"); - pout("Temperature warning %s\n", - scsi_IsWarningEnabled(&iec) ? "enabled" : "disabled"); - return 0; -} - -void scsiPrintTemp(int device) -{ - UINT8 temp = 0; - UINT8 trip = 0; - - if (scsiGetTemp(device, &temp, &trip)) - return; - - if (temp) { - if (255 != temp) - pout("Current Drive Temperature: %d C\n", temp); - else - pout("Current Drive Temperature: <not available>\n"); - } - if (trip) - pout("Drive Trip Temperature: %d C\n", trip); -} - -// Compares failure type to policy in effect, and either exits or -// simply returns to the calling routine. -static void failuretest(int type, int returnvalue) -{ - // If this is an error in an "optional" SMART command - if (type == OPTIONAL_CMD) { - if (con->conservative) { - pout("An optional SMART command has failed: exiting.\n" - "To continue, set the tolerance level to something other " - "than 'conservative'\n"); - exit(returnvalue); - } - } - return; -} - - -/* Main entry point used by smartctl command. Return 0 for success */ -int scsiPrintMain(const char *dev_name, int fd) -{ - int checkedSupportedLogPages = 0; - UINT8 peripheral_type = 0; - int returnval=0; - int res; - - if (scsiGetDriveInfo(fd, &peripheral_type, con->driveinfo)) { - pout("Smartctl: SCSI device INQUIRY Failed\n\n"); - failuretest(MANDATORY_CMD, returnval |= FAILID); - } - - if (con->smartenable) { - if (scsiSmartEnable(fd)) - failuretest(MANDATORY_CMD, returnval |= FAILSMART); - } - - if (con->smartdisable) { - if (scsiSmartDisable(fd)) - failuretest(MANDATORY_CMD,returnval |= FAILSMART); - } - - if (con->checksmart) { - scsiGetSupportedLogPages(fd); - checkedSupportedLogPages = 1; - if ((SCSI_PT_SEQUENTIAL_ACCESS == peripheral_type) || - (SCSI_PT_MEDIUM_CHANGER == peripheral_type)) { /* tape device */ - if (gTapeAlertsPage) { - if (con->driveinfo) - pout("TapeAlert Supported\n"); - if (-1 == scsiGetTapeAlertsData(fd, peripheral_type)) - failuretest(OPTIONAL_CMD, returnval |= FAILSMART); - } - else - pout("TapeAlert Not Supported\n"); - if (gTempPage) - scsiPrintTemp(fd); - if (gStartStopPage) - scsiGetStartStopData(fd); - } else { /* disk, cd/dvd, enclosure, etc */ - scsiGetSmartData(fd); - if (gTempPage) - scsiPrintTemp(fd); - if (gStartStopPage) - scsiGetStartStopData(fd); - } - } - if (con->smarterrorlog) - scsiPrintErrorCounterLog(fd); - if (con->smartselftestlog) { - if (! checkedSupportedLogPages) - scsiGetSupportedLogPages(fd); - res = 0; - if (gSelfTestPage) - res = scsiPrintSelfTest(fd); - else { - pout("Warning: device does not support Self Test Logging\n"); - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - } - if (0 != res) - failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - } - if (con->smartexeoffimmediate) { - if (scsiSmartDefaultSelfTest(fd)) { - pout( "Default Self Test Failed\n"); - return returnval; - } - pout("Default Self Test Successful\n"); - } - if (con->smartshortcapselftest) { - if (scsiSmartShortCapSelfTest(fd)) { - pout("Short Foreground Self Test Failed\n"); - return returnval; - } - pout("Short Foreground Self Test Successful\n"); - } - if (con->smartshortselftest ) { - if ( scsiSmartShortSelfTest(fd)) { - pout("Short Background Self Test Failed\n"); - return returnval; - } - pout("Short Background Self Test has begun\n"); - pout("Use smartctl -X to abort test\n"); - } - if (con->smartextendselftest) { - if (scsiSmartExtendSelfTest(fd)) { - pout("Extended Background Self Test Failed\n"); - return returnval; - } - pout("Extended Background Self Test has begun\n"); - pout("Use smartctl -X to abort test\n"); - } - if (con->smartextendcapselftest) { - if (scsiSmartExtendCapSelfTest(fd)) { - pout("Extended Foreground Self Test Failed\n"); - return returnval; - } - pout("Extended Foreground Self Test Successful\n"); - } - if (con->smartselftestabort) { - if (scsiSmartSelfTestAbort(fd)) { - pout("Self Test Abort Failed\n"); - return returnval; - } - pout("Self Test returned without error\n"); - } - return returnval; -} diff --git a/sm5/scsiprint.h b/sm5/scsiprint.h deleted file mode 100644 index e5b410365..000000000 --- a/sm5/scsiprint.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * scsiprint.h - * - * Home page of code is: http://smartmontools.sourceforge.net - * - * Copyright (C) 2002-3 Bruce Allen <smartmontools-support@lists.sourceforge.net> - * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org> - * - * 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 Software Foundation; either version 2, or (at your option) - * any later version. - * - * You should have received a copy of the GNU General Public License - * (for example COPYING); if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * This code was originally developed as a Senior Thesis by Michael Cornwell - * at the Concurrent Systems Laboratory (now part of the Storage Systems - * Research Center), Jack Baskin School of Engineering, University of - * California, Santa Cruz. http://ssrc.soe.ucsc.edu/ - * - */ - - -/* scsismart version number */ -#ifndef SCSI_PRINT_H_ -#define SCSI_PRINT_H_ - -#ifndef SCSIPRINT_H_CVSID -#define SCSIPRINT_H_CVSID "$Id: scsiprint.h,v 1.13 2003/05/01 08:49:04 dpgilbert Exp $\n" -#endif - -// MACROS to control printing behavior (from ataprint.h) -#define QUIETON(control) {if (control->quietmode) control->veryquietmode=0;} -#define QUIETOFF(control) {if (control->quietmode && !control->veryquietmode) control->veryquietmode=1;} - -int scsiPrintMain(const char * dev_name, int fd); - -#endif diff --git a/sm5/smartctl.8 b/sm5/smartctl.8 deleted file mode 100644 index e6fb01311..000000000 --- a/sm5/smartctl.8 +++ /dev/null @@ -1,890 +0,0 @@ -\# Copyright (C) 2002-3 Bruce Allen <smartmontools-support@lists.sourceforge.net> -\# -\# $Id: smartctl.8,v 1.68 2003/04/21 22:43:04 ballen4705 Exp $ -\# -\# 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 -\# Software Foundation; either version 2, or (at your option) any later -\# version. -\# -\# You should have received a copy of the GNU General Public License (for -\# example COPYING); if not, write to the Free Software Foundation, Inc., 675 -\# Mass Ave, Cambridge, MA 02139, USA. -\# -\# This code was originally developed as a Senior Thesis by Michael Cornwell -\# at the Concurrent Systems Laboratory (now part of the Storage Systems -\# Research Center), Jack Baskin School of Engineering, University of -\# California, Santa Cruz. http://ssrc.soe.ucsc.edu/ -\# -.TH SMARTCTL 8 "$Date: 2003/04/21 22:43:04 $" "smartmontools-5.1" -.SH NAME -smartctl \- Control and Monitor Utility for SMART Disks -.SH SYNOPSIS -.B smartctl [options] device - -.SH DESCRIPTION -.B smartctl -controls the Self-Monitoring, Analysis and Reporting Technology -(SMART) system built into many ATA-3 and later ATA, IDE and -SCSI-3 hard drives. The purpose of SMART is to monitor the -reliability of the hard drive and predict drive failures, and to carry -out different types of drive self-tests. This version of \fB smartctl\fP is -compatible with ATA/ATAPI-5 and earlier standards (see REFERENCES -below) - -.B smartctl -is a command line utility designed to perform SMART tasks such as -printing the SMART self-test and error logs, and enabling and -disabling SMART automatic testing. Note: if the user issues a -SMART command that is (apparently) not implemented by the device, -.B smartctl -will print a warning message but issue the command anyway. This should -not cause problems: unimplemented SMART commands issued to a -drive are ignored and return an error. - -.B smartctl -also provides limited TapeAlerts support for some SCSI tape drives and -changers. - -The user must specify the device to be controlled or interrogated as the final -argument to -.B smartctl. -ATA devices use the form "/dev/hd*" and SCSI devices use the form "/dev/sd*". -For SCSI Tape Drives and Changers with TapeAlerts support use the devices -"/dev/st*" and "/dev/sg*". More general paths may also be specified. -.B smartctl -will attempt to guess the device type, but the '\-d' option can be used to -specify a device type of ATA or SCSI if required. - -Note that the printed output of -.B smartctl -displays most numerical values in base 10 (decimal), but some values -are displayed in base 16 (hexidecimal). To distinguish them, the base -16 values are always displayed with a leading -.B "0x" -for example: "0xff". This man page follows the same convention. - -.PP -.SH OPTIONS -.PP -The options are grouped below into several categories. -.B smartctl -will execute the corresponding commands in the order: INFORMATION, -ENABLE/DISABLE, DISPLAY DATA, RUN/ABORT TESTS. - -SCSI devices only accept the options -.B \-h, \-?, \-V, \-i, \-a, \-d, \-s, \-H, \-t, \-C, \-l selftest, \-l error -and -.B \-X. -TapeAlerts devices only accept the options -.B \-h, \-?, \-V, \-i, \-a, \-d, \-s, \-t, \-l selftest, \-l error -and -.B \-H. - -Long options are not supported on all systems. Use -.B 'smartctl \-h' -to see the available options. - -.TP -.B SHOW INFORMATION: -.TP -.B \-h, \-\-help, \-\-usage -Prints a usage message to STDOUT and exits. -.TP -.B \-? -Same as -.B \-h. -.TP -.B \-V, \-\-version, \-\-copyright, \-\-license -Prints version, copyright, license, home page and CVS-id information for your -copy of -.B smartctl -to STDOUT and then exits. Please include this information if you are -reporting bugs or problems. -.TP -.B \-i, \-\-info -Prints the disk model number, serial number, firmware version, and ATA Standard -version/revision information. Says if the device supports SMART, and if -so, whether SMART support is currently enabled or disabled. -.TP -.B \-a, \-\-all -Prints all SMART information about the disk. This is equivalent to '\-H -\-i \-c \-A \-l error \-l selftest' (for SCSI, '\-H \-i \-l error -\-l selftest'). -.TP -.B RUN-TIME BEHAVIOR: -.TP -.B \-q TYPE, \-\-quietmode=TYPE -Specifies that -.B smartctl -should run in one of the two quiet modes described here. The valid arguments -to this option are: - -.I errorsonly -\- only print: For the '\-l error' option, if nonzero, the number -of errors recorded in the SMART error log and the power-on time when -they occurred; For the '\-l selftest' option, errors recorded in the device -self-test log; For the '\-H' option, SMART "disk failing" status or device -Attributes (pre-failure or usage) which failed either now or in the -past; For the '\-A' option, device Attributes (pre-failure or usage) -which failed either now or in the past. - -.I silent -\- print no output. The only way to learn about what was -found is to use the exit status of -.B smartctl -(see RETURN VALUES below). -.TP -.B \-d TYPE, \-\-device=TYPE -Specifies the type of the device. The valid arguments to this option -are \fIata\fP and \fIscsi\fP. If this option is not used then -.B smartctl -will attempt to guess the device type from the device name. -.TP -.B \-T TYPE, \-\-tolerance=TYPE -Specifies how tolerant -.B smartctl -should be of SMART command failures. The valid arguments to this option -are: - -.I normal -\- exit on failure of a mandatory SMART command, but not on failure of an -optional SMART command. This is the default. - -.I conservative -\- exit on failure of any SMART command. - -.I permissive -\- ignore failure of any SMART command. - -Here "mandatory" means "required by the ATA/ATAPI-5 Specification if the -device implements the SMART command set" and "optional" means "not -required by the ATA/ATAPI-5 Specification even if the device implements -the SMART command set." The 'mandatory' SMART commands are: (1) -Enable/Disable Attribute Autosave, (2) Enable/Disable SMART, and (3) -SMART Return Status. - -.TP -.B \-b TYPE, \-\-badsum=TYPE -Specifies the action -.B smartctl -should take if a checksum error is detected in the: (1) Device -Identity Structure, (2) SMART Self-Test Log Structure, (3) -SMART Attribute Value Structure, (4) SMART Attribute -Threshold Structure, or (5) ATA Error Log Structure. - -The valid arguments to this option are: - -.I warn -\- report the incorrect checksum but carry on in spite of it. This is the -default. - -.I exit -\- exit -.B smartctl. - -.I ignore -\- continue silently without issuing a warning. - -.TP -.B \-r TYPE, \-\-report=TYPE -Intended primarily to help -.B smartmontools -developers understand the behavior of -.B smartmontools -on non-conforming or poorly conforming hardware. This option reports -details of -.B smartctl -transactions with the device. The option can be used multiple times. -When used just once, it shows a record of the ioctl() transactions -with the device. When used more than once, the detail of these ioctl() -transactions are reported in greater detail. The valid arguments to -this option are: - -.I ioctl -\- report all ioctl() transactions. - -.I ataioctl -\- report only ioctl() transactions with ATA devices. - -.I scsiioctl -\- report only ioctl() transactions with SCSI devices. Invoking this once -shows the SCSI commands in hex and the corresponding status. Invoking -it a second time adds a hex listing of the first 64 bytes of data send to, -or received from the device. - -Any argument may include a positive integer to specify the level of detail -that should be reported. The argument should be followed by a comma then -the integer with no spaces. For example, -.I ataioctl,2 -The default -level is 1, so '\-r ataioctl,1' and '\-r ataioctl' are equivalent. - -.TP -.B SMART FEATURE ENABLE/DISABLE COMMANDS: -.IP -.B Note: -if multiple options are used to both enable and disable a -feature, then -.B both -the enable and disable commands will be issued. The enable command -will always be issued -.B before -the corresponding disable command. -.TP -.B \-s VALUE, \-\-smart=VALUE -Enables or disables SMART on device. The valid arguments to -this option are \fIon\fP and \fIoff\fP. Note that the command '\-s on' -(perhaps used with with the '\-o on' and '\-S on' options) should be placed -in a start-up script for your machine, for example in rc.local or rc.sysinit. -In principle the SMART feature settings are preserved over -power-cycling, but it doesn't hurt to be sure. -.TP -.B \-o VALUE, \-\-offlineauto=VALUE -Enables or disables SMART automatic offline test, which scans the drive -every four hours for disk defects. This command can be given during normal -system operation. The valid arguments to this option are \fIon\fP -and \fIoff\fP. - -Note that the SMART automatic offline test command is listed as 'Obsolete' -in every version of the ATA and ATA/ATAPI Specifications -that I can find. However it is implemented and used by some -vendors. [Good documentation can be found in IBM's Official -Published Disk Specifications. For example the IBM Travelstar 40GNX -Hard Disk Drive Specifications (Revision 1.1, 22 April 2002, -Publication # 1541, Document S07N-7715-02) page 164.] -You can tell if automatic offline testing is supported by seeing if -this command enables and disables it, as indicated by the SMART -capabilities (displayed with '\-c'). - -SMART provides -.B three basic categories of testing. -The -.B first category, -called 'online' testing, has no effect on the performance of -the device. It is turned on by the '\-s on' option. - -The -.B second category of testing -is called 'offline' testing. This type -of test can, in principle, degrade the device performance. The '\-o on' -option causes this offline testing to be carried out, automatically, -on a regular scheduled basis. Normally, the disk will suspend -offline testing while disk accesses are taking place, and then -automatically resume it when the disk would otherwise be idle, so in -practice it has little effect. Note that a one-time offline test can -also be carried out immediately upon receipt of a user command. See -the '\-t offline' option below, which causes a one-time offline test to be -carried out immediately. - -Any errors detected in automatic or immediate offline testing are -reflected in the values of the SMART Attributes; some types of -errors may also appear in the SMART error log. These are visible -with the '\-A' and '\-l error' options respectively. - -The -.B third category of testing -is the 'self' testing. This third type of -test is only performed (immediately) when a command to run it is -issued. The '\-t' and '\-X' options can be used to carry out and abort such -self-tests; please see below for further details. - -Any errors detected in the self testing will be shown in the -SMART self-test log, which can be examined using the '\-l selftest' -option. - -.B Note: -in this manual page, the word -.B "Test" -is used in connection with the second category -just described, e.g. for the 'offline' testing. The words -.B "Self-test" -are used in connection with the third category. -.TP -.B \-S VALUE, \-\-saveauto=VALUE -Enables or disables SMART autosave of device vendor-specific -Attributes. The valid arguments to this option are \fIon\fP -and \fIoff\fP. Note that this feature is preserved across disk power -cycles, so you should only need to issue it once. -.TP -.B SMART READ AND DISPLAY DATA OPTIONS: -.TP -.B \-H, \-\-health -Check: Ask the device to report its SMART health status. It does -this using information that it has gathered from online and offline -tests, which were used to determine/update its -SMART vendor-specific Attribute values. - -If the device reports failing health status, this means -.B either -that the device has already failed, -.B or -that it is predicting its own failure within the next 24 hours. If -this happens, use the '\-a' option to get more information, and -.B get your data off the disk and someplace safe as soon as you can. -.TP -.B \-c, \-\-capabilities -Prints only the generic SMART capabilities. These show -what SMART features are implemented and how the device will -respond to some of the different SMART commands. For example it -shows if the device logs errors, if it supports offline surface -scanning, and so on. If the device can carry out self-tests, this -option also shows the estimated time required to run those tests. - -Note that the time required to run the Self-tests (listed in minutes) -are fixed. However the time required to run the Immediate Offline -Test (listed in seconds) is variable. This means that if you issue a -command to perform an Immediate Offline test with the '\-t offline' option, -then the time may jump to a larger value and then count down as the -Immediate Offline Test is carried out. Please see REFERENCES below -for further information about the the flags and capabilities described -by this option. -.TP -.B \-A, \-\-attributes -Prints only the vendor specific SMART Attributes. The -Attributes are numbered from 1 to 253 and have specific names. For -example Attribute 12 is 'power cycle count': how many times has the -disk been powered up. - -Each Attribute has a 'Raw' value, printed under the heading 'RAW_VALUE', -and a 'Normalized' value printed under the heading 'VALUE'. [Note: -.B smartctl -prints these values in base-10.] In the example just given, the 'Raw -Value' for Attribute 12 would be the actual number of times that the -disk has been power-cycled, for example 365 if the disk has been -turned on once per day for exactly one year. Each vendor uses their -own algorithm to convert this Raw value to a Normalized value in the -range from 1 to 254. Note that -.B smartctl -only reports the different Attribute values and thresholds. It does -.B not -carry out the conversion between 'Raw' and 'Normalized' values. - -Note that the conversion from 'Raw' value to a quantity with physical -units is not specified by the SMART standard. In most cases, the -values printed by -.B smartctl -are sensible. For example the temperature Attribute generally has its -raw value equal to the temperature in Celsius. However in some cases -vendors use unusual conventions. For example the Hitachi disk on my -laptop reports its power-on hours in minutes, not hours. Some IBM -disks track three temperatures rather than one, in their raw values. -And so on. - -Each Attribute also has a Threshold value (whose range is 0 to 255) -which is printed under the heading 'THRESH'. If the Normalized value -is -.B less than or equal to -the Threshold value, then the Attribute is said to have failed. If -the Attribute is a pre-failure Attribute, then disk failure is -imminent. - -Each Attribute also has a 'Worst' value shown under the heading 'WORST'. -This is the smallest (closest to failure) value that the -disk has recorded at any time during its lifetime when SMART was -enabled. [Note however that some vendors will have firmware which will -.B increase -the 'Worst' value for some "rate-type" Attributes.] - -The Attribute table printed out by -.B smartctl -also shows the 'Type' of the Attribute. Pre-failure Attributes are -ones which, if less than or equal to their threshold values, indicate -pending disk failure. Old age, or usage Attributes, are ones which -indicate end-of-product life from old-age or normal aging and wearout, -if the Attribute value is less than or equal to the threshold. - -If the Attribute's current Normalized value is <= threshold, then the 'Ever -failed' column will display 'FAILED NOW!'. If not, but the worst -recorded value is <= threshold, then this column will display 'In the -past'. - -So to summarize: the 'Raw' values are the ones that might have a real -physical interpretation, such as 'Temperature Celsius', 'Hours', or 'Start-Stop Cycles'. -Each manufacturer converts these, using their -detailed knowledge of the disk's operations and failure modes, to -Normalized Attribute values in the range 1-254. The worst (lowest -measured) of these Normalized Attribute values is stored on the disk, -along with a Threshold value that the manufacturer has determined will -indicate that the disk is going to fail, or that it has exceeded its -design age or aging limit. -.B smartctl -does not calculate any of these values, it merely reports them from -the SMART data on the disk. - -Note that starting with ATA/ATAPI-4, revision 4, the meaning of these -Attribute fields has been made entirely vendor-specific. However most -ATA/ATAPI-5 disks seem to respect their meaning, so we have retained -the option of printing the Attribute values. -.TP -.B \-l TYPE, \-\-log=TYPE -Prints either the SMART error log or the SMART self-test log. The -valid arguments to this option are: - -.I error -\- prints only the SMART error log. SMART disks maintain a -log of the most recent five non-trivial errors. For each of these -errors, the disk power-on lifetime at which the error occurred is -recorded, as is the device status (idle, standby, etc) at the time of -the error. Finally, up to the last five commands that preceded the -error are also recorded, along with a timestamp measured in seconds -from when the disk was powered up during the session where the error -took place. [Note: this time stamp wraps after 2^32 milliseconds, or -49 days 17 hours 2 minutes and 47.296 seconds.] The key ATA disk -registers are also recorded in the log. - -The ATA Specification (ATA-5 Revision 1c, Section 8.41.6.8.2 to be -precise) says "Error log structures shall include UNC errors, IDNF -errors for which the address requested was valid, servo errors, write -fault errors, etc. Error log data structures shall not include errors -attributed to the receipt of faulty commands such as command codes not -implemented by the device or requests with invalid parameters or -invalid addresses." - -.I error [SCSI] -\- prints the error counter log pages for reads, write and verifies. -The verify row is only output if it has an element other than zero. - -.I selftest -\- prints only the SMART self-test log. The disk maintains a log -showing the results of the self tests, which can be run using the -\'\-t' option described below. For each of the most recent twenty-one -self-tests, the log shows the type of test (short or extended, -off-line or captive) and the final status of the test. If the test -did not complete successfully, then the percentage of the test -remaining is shown. The time at which the test took place, measured -in hours of disk lifetime, is also printed. If any errors were -detected, the Logical Block Address (LBA) of the first error is -printed in hexadecimal notation. - -.I selftest [SCSI] -\- the self-test log for a SCSI device has a slightly different format -than for an ATA device. For each of the most recent twenty -self-tests, it shows the type of test and the status (final or in -progress) of the test. SCSI standards use the terms 'foreground' and -\'background' (rather than ATA's corresponding 'captive' and -\'off-line') and \'short' and 'long' (rather than ATA's corresponding -\'short' and 'extended') to describe the type of the test. The printed -segment number is only relevant when a test fails in the third or -later test segment. It identifies the test that failed and consists -of either the number of the segment that failed during the test, or -the number of the test that failed and the number of the segment in -which the test was run, using a vendor-specific method of putting both -numbers into a single byte. The Logical Block Address (LBA) of the -first error is printed in hexadecimal notation. If provided, the SCSI -Sense Key (SK), Additional Sense Code (ASC) and Additional Sense Code -Qualifier (ASQ) are also printed. The self tests can be run using the -\'\-t' option described below (using the ATA test terminology). - -.I directory -\- if the device supports the General Purpose Logging feature set -(ATA-6 and ATA-7 only) then this prints the Log Directory (the log at -address 0). The Log Directory shows what logs are available and their -length in sectors (512 bytes). The contents of the logs at address 1 -[Summary SMART error log] and at address 6 [SMART self-test log] may -be printed using the previously-described -.I error -and -.I selftest -arguments to this option. [Please note: this is a new, experimental -feature. We would like to add support for printing the contents of -extended and comprehensive SMART self-test and error logs. If your -disk supports these, and you would like to assist, please contact the -smartmontools developers.] - -.TP -.B \-v N,OPTION, \-\-vendorattribute=N,OPTION -Sets a vendor-specific display OPTION for Attribute N. This option -may be used multiple times. Valid arguments to this option are: - -.I 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 -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 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) option. - -.I 200,writeerrorcount -\- Raw Attribute number 200 is the Write Error 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: -http://coredump.free.fr/linux/hddtemp.db - -.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 -Modifies the behavior of -.B smartctl -to compensate for some known and understood device firmware bug. The -valid arguments to this option are: - -.I none -Assume that the device firmware obeys the ATA specifications. This is -the default. - -.I samsung -In some Samsung disks (example: model SV4012H Firmware Version: -RM100-08) some of the two- and four-byte quantities in the SMART data -structures are byte-swapped (relative to the ATA specification). -Enabling this option tells -.B smartctl -to evaluate these quantities in byte-reversed order. Some signs that -your disk needs this option are (1) no self-test log printed, even -though you have run self-tests; (2) very large numbers of ATA errors -reported in the ATA erorr log; (3) strange and impossible values for -the ATA error log timestamps. - -.TP -.B \-P TYPE, \-\-presets=TYPE -Specifies whether -.B smartctl -should use any preset options that are available for this drive. By -default, if the drive is recognized in the smartmontools database, -then the presets are used. - -.B smartctl -can automatically set appropriate options for known drives. For -example, the Maxtor 4D080H4 uses Attribute 9 to stores power-on time -in minutes whereas most drives use that Attribute to store the -power-on time in hours. The command-line option '-v 9,minutes' -ensures that -.B smartctl -correctly interprets Attribute 9 in this case, but that option is -preset for the Maxtor 4D080H4 and so need not be specified by the user -on the -.B smartctl -command line. - -The argument -.I show -will show any preset options for your drive and the argument -.I showall -will show all known drives in the smartmontools database, along with -their preset options. If there are no presets for your drive and you -think there should be (for example, a \-v or \-F option is needed to -get -.B smartctl -to display correct values) then please contact the -.B smartmontools -developers so that this information can be added to the smartmontools -database. Contact information is at the end of this man page. - -The valid arguments to this option are: - -.I use -\- if a drive is recognized, then use the stored presets for it. This -is the default. Note that presets will NOT over-ride additional -Attribute interpretation ('-v N,something') command-line options. - -.I ignore -\- do not use presets. - -.I show -\- show if the drive is recognized in the database, and if so, its -presets, then exit. - -.I showall -\- list all recognized drives, and the presets that are set for them, -then exit. - -.TP -.B SMART RUN/ABORT OFFLINE TEST AND SELF-TEST OPTIONS: -.TP -.B \-t TEST, \-\-test=TEST -Executes TEST immediately. The '\-C' option can be used in -conjunction with this option to run the short or long self-tests in -captive mode (known as 'foreground mode' for SCSI devices). Note that -only one test can be run at a time, so this option should only be used -once per command line. - -The valid arguments to this option are: - -.I offline -\- runs SMART Immediate Offline Test. This immediately -starts the test described above. This command can be given during -normal system operation. The effects of this test are visible only in -that it updates the SMART Attribute values, and if errors are -found they will appear in the SMART error log, visible with the '\-l error' -option. [In the case of SCSI devices runs the default self test in -foreground. No entry is placed in the self test log.] - -If the '\-c' option to -.B smartctl -shows that the device has the "Suspend Offline collection upon new -command" capability then you can track the progress of the Immediate Offline -test using the '\-c' option to -.B smartctl. -If the '\-c' option show that the device has the "Abort Offline -collection upon new command" capability then most commands will abort -the Immediate Offline Test, so you should not try to track the -progress of the test with '\-c', as it will abort the test. - -.I short -\- runs SMART Short Self Test (usually under ten minutes). -[Note: in the case of SCSI devices, -this command option runs the 'Background short' self-test.] -This command can be given during normal system operation (unless run in -captive mode \- see the '\-C' option below). This is a -test in a different category than the immediate or automatic offline -tests. The 'Self' tests check the electrical and mechanical -performance as well as the read performance of the disk. Their -results are reported in the Self Test Error Log, readable with -the '\-l selftest' option. Note that on some disks the progress of the -self-test can be monitored by watching this log during the self-test; with other disks -use the '\-c' option to monitor progress. - -.I long -\- runs SMART Extended Self Test (tens of minutes). -[Note: in the case of SCSI devices, -this command option runs the 'Background long' self-test.] -This is a -longer and more thorough version of the Short Self Test described -above. Note that this command can be given during normal -system operation (unless run in captive mode \- see the '\-C' option below). - -.TP -.B \-C, \-\-captive -With '\-t short' or '\-t long', runs the self-test in captive mode. This has -no effect with '\-t offline' or if the '\-t' option is not used. [Note: in the case -of SCSI devices, this command option runs the self-test in 'Foreground' mode.] - -.B WARNING: Tests run in captive mode may busy out the drive for the length -.B of the test. Only run captive tests on drives without any mounted partitions! - -.TP -.B \-X, \-\-abort -Aborts non-captive SMART Self Tests. Note that this -command will abort the Offline Immediate Test routine only if your -disk has the "Abort Offline collection upon new command" capability. -.PP -.SH EXAMPLES -.nf -.B smartctl \-a /dev/hda -.fi -Print all SMART information for drive /dev/hda (Primary Master). -.PP -.nf -.B smartctl \-s off /dev/hdd -.fi -Disable SMART on drive /dev/hdd (Secondary Slave). -.PP -.nf -.B smartctl \-\-smart=on \-\-offlineauto=on \-\-saveauto=on /dev/hda -.fi -Enable SMART on drive /dev/hda, enable automatic offline -testing every four hours, and enable autosaving of -SMART Attributes. This is a good start-up line for your system's -init files. You can issue this command on a running system. -.PP -.nf -.B smartctl \-t long /dev/hdc -.fi -Begin an extended self-test of drive /dev/hdc. You can issue this -command on a running system. The results can be seen in the self-test -log visible with the '\-l selftest' option after it has completed. -.PP -.nf -.B smartctl \-s on \-t offline /dev/hda -.fi -Enable SMART on the disk, and begin an immediate offline test of -drive /dev/hda. You can issue this command on a running system. The -results are only used to update the SMART Attributes, visible -with the '\-A' option. If any device errors occur, they are logged to -the SMART error log, which can be seen with the '\-l error' option. -.PP -.nf -.B smartctl \-A \-v 9,minutes /dev/hda -.fi -Shows the vendor Attributes, when the disk stores its power-on time -internally in minutes rather than hours. -.PP -.nf -.B smartctl \-q errorsonly \-H \-l selftest /dev/hda -.fi -Produces output only if the device returns failing SMART status, -or if some of the logged self-tests ended with errors. -.PP -.nf -.B smartctl \-q silent \-a /dev/hda -.fi -Examine all SMART data for device /dev/hda, but produce no -printed output. You must use the exit status (the -.B $? -shell variable) to learn if any Attributes are out of bound, if the -SMART status is failing, if there are errors recorded in the -self-test log, or if there are errors recorded in the disk error log. - -.PP -.SH RETURN VALUES -The return values of smartctl are defined by a bitmask. For the -moment this only works on ATA disks. The different bits in the return -value are as follows: -.TP -.B Bit 0: -Command line did not parse. -.TP -.B Bit 1: -Device open failed, or device did not return an IDENTIFY DEVICE structure. -.TP -.B Bit 2: -Some SMART command to the disk failed, or there was a checksum error -in a SMART data structure (see '\-b' option above). -.TP -.B Bit 3: -SMART status check returned "DISK FAILING". -.TP -.B Bit 4: -SMART status check returned "DISK OK" but we found prefail Attributes <= threshold. -.TP -.B Bit 5: -SMART status check returned "DISK OK" but we found that some (usage -or prefail) Attributes have been <= threshold at some time in the -past. -.TP -.B Bit 6: -The device error log contains records of errors. -.TP -.B Bit 7: -The device self-test log contains records of errors. - -To test within the shell for whether or not the different bits are -turned on or off, you can use the following type of construction (this -is bash syntax): -.nf -.B smartstat=$(($? & 8)) -.fi -This looks at only at bit 3 of the exit status -.B $? -(since 8=2^3). The shell variable -$smartstat will be nonzero if SMART status check returned 'disk -failing' and zero otherwise. - -.PP -.SH AUTHOR -Bruce Allen -.B smartmontools-support@lists.sourceforge.net -.fi -University of Wisconsin \- Milwaukee Physics Department - -.PP -.SH CREDITS -.fi -This code was derived from the smartsuite package, written by Michael -Cornwell, and from the previous ucsc smartsuite package. It extends -these to cover ATA-5 disks. This code was originally developed as a -Senior Thesis by Michael Cornwell at the Concurrent Systems Laboratory -(now part of the Storage Systems Research Center), Jack Baskin School -of Engineering, University of California, Santa -Cruz. http://ssrc.soe.ucsc.edu/. -.SH -HOME PAGE FOR SMARTMONTOOLS: -.fi -Please see the following web site for updates, further documentation, bug -reports and patches: -.nf -.B -http://smartmontools.sourceforge.net/ - -.SH -SEE ALSO: -.B -smartd (8) -.SH -REFERENCES FOR SMART -.fi -If you would like to understand better how SMART works, and what -it does, a good place to start is Section 8.41 of the 'AT -Attachment with Packet Interface-5' (ATA/ATAPI-5) specification. This -documents the SMART functionality which the smartmontools -utilities provide access to. You can find Revision 1 of this document -at: -.nf -.B -http://www.t13.org/project/d1321r1c.pdf -.fi -Future versions of the specifications (ATA/ATAPI-6 and ATA/ATAPI-7), -and later revisions (2, 3) of the ATA/ATAPI-5 specification are -available from: -.nf -.B -http://www.t13.org/#FTP_site - -.fi -The functioning of SMART is also described by the SFF-8035i -revision 2 specification. This is a publication of the Small Form -Factors (SFF) Committee, and can be obtained from: -.TP -\ -SFF Committee -.nf -14426 Black Walnut Ct. -.nf -Saratoga, CA 95070, USA -.nf -SFF FaxAccess: +01 408-741-1600 -.nf -Ph: +01 408-867-6630 -.nf -Fax: +01 408-867-2115 -.nf -E-Mail: 250-1752@mcimail.com. -.PP -Please let us know if there is an on\-line source for this document. - -.SH -CVS ID OF THIS PAGE: -$Id: smartctl.8,v 1.68 2003/04/21 22:43:04 ballen4705 Exp $ diff --git a/sm5/smartctl.c b/sm5/smartctl.c deleted file mode 100644 index 8fbdf0a1f..000000000 --- a/sm5/smartctl.c +++ /dev/null @@ -1,714 +0,0 @@ -/* - * smartctl.c - * - * Home page of code is: http://smartmontools.sourceforge.net - * - * Copyright (C) 2002-3 Bruce Allen <smartmontools-support@lists.sourceforge.net> - * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org> - * - * 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 Software Foundation; either version 2, or (at your option) - * any later version. - * - * You should have received a copy of the GNU General Public License - * (for example COPYING); if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * This code was originally developed as a Senior Thesis by Michael Cornwell - * at the Concurrent Systems Laboratory (now part of the Storage Systems - * Research Center), Jack Baskin School of Engineering, University of - * California, Santa Cruz. http://ssrc.soe.ucsc.edu/ - * - */ - - -#include <stdio.h> -#include <unistd.h> -#include <sys/ioctl.h> -#include <linux/hdreg.h> -#include <sys/fcntl.h> -#include <sys/types.h> -#include <string.h> -#include <stdarg.h> -#ifdef HAVE_GETOPT_H -#include <getopt.h> -#endif -#include "atacmds.h" -#include "ataprint.h" -#include "extern.h" -#include "knowndrives.h" -#include "scsicmds.h" -#include "scsiprint.h" -#include "smartctl.h" -#include "utility.h" - -extern const char *atacmds_c_cvsid, *ataprint_c_cvsid, *knowndrives_c_cvsid, *scsicmds_c_cvsid, *scsiprint_c_cvsid, *utility_c_cvsid; -const char* smartctl_c_cvsid="$Id: smartctl.c,v 1.76 2003/05/01 08:51:46 dpgilbert Exp $" -ATACMDS_H_CVSID ATAPRINT_H_CVSID EXTERN_H_CVSID KNOWNDRIVES_H_CVSID SCSICMDS_H_CVSID SCSIPRINT_H_CVSID SMARTCTL_H_CVSID UTILITY_H_CVSID; - -// This is a block containing all the "control variables". We declare -// this globally in this file, and externally in other files. -smartmonctrl *con=NULL; - - -void printslogan(){ - pout("smartctl version %d.%d-%d Copyright (C) 2002-3 Bruce Allen\n", - (int)RELEASE_MAJOR, (int)RELEASE_MINOR, (int)SMARTMONTOOLS_VERSION); - pout("Home page is %s\n\n",PROJECTHOME); - return; -} - - -void printcopy(){ - char out[CVSMAXLEN]; - pout("smartctl comes with ABSOLUTELY NO WARRANTY. This\n"); - pout("is free software, and you are welcome to redistribute it\n"); - pout("under the terms of the GNU General Public License Version 2.\n"); - pout("See http://www.gnu.org for further details.\n\n"); - pout("CVS version IDs of files used to build this code are:\n"); - printone(out,atacmds_c_cvsid); - pout("%s",out); - printone(out,ataprint_c_cvsid); - pout("%s",out); - printone(out,knowndrives_c_cvsid); - pout("%s",out); - printone(out,scsicmds_c_cvsid); - pout("%s",out); - printone(out,scsiprint_c_cvsid); - pout("%s",out); - printone(out,smartctl_c_cvsid); - pout("%s",out); - printone(out,utility_c_cvsid); - pout("%s",out); - return; -} - -/* void prints help information for command syntax */ -void Usage (void){ - printf("Usage: smartctl [options] device\n\n"); - printf("============================================ SHOW INFORMATION OPTIONS =====\n\n"); -#ifdef HAVE_GETOPT_LONG - printf( -" -h, -?, --help, --usage\n" -" Display this help and exit\n\n" -" -V, --version, --copyright, --license\n" -" Print license, copyright, and version information and exit\n\n" -" -i, --info \n" -" Show identity information for device\n\n" -" -a, --all \n" -" Show all SMART information for device\n\n" - ); -#else - printf( -" -h, -? Display this help and exit\n" -" -V Print license, copyright, and version information\n" -" -i Show identity information for device\n" -" -a Show all SMART information for device\n\n" - ); -#endif - printf("================================== SMARTCTL RUN-TIME BEHAVIOR OPTIONS =====\n\n"); -#ifdef HAVE_GETOPT_LONG - printf( -" -q TYPE, --quietmode=TYPE (ATA)\n" -" Set smartctl quiet mode to one of: errorsonly, silent\n\n" -" -d TYPE, --device=TYPE\n" -" Specify device type to one of: ata, scsi\n\n" -" -T TYPE, --tolerance=TYPE (ATA)\n" -" Set tolerance to one of: normal, conservative, permissive\n\n" -" -b TYPE, --badsum=TYPE (ATA)\n" -" Set action on bad checksum to one of: warn, exit, ignore\n\n" -" -r TYPE, --report=TYPE\n" -" Report transactions (see man page)\n\n" - ); -#else - printf( -" -q TYPE Set smartctl quiet mode to one of: errorsonly, silent (ATA)\n" -" -d TYPE Specify device type to one of: ata, scsi\n" -" -T TYPE Set tolerance to one of: normal, conservative, permissive (ATA)\n" -" -b TYPE Set action on bad checksum to one of: warn, exit, ignore (ATA)\n" -" -r TYPE Report transactions (see man page)\n\n" - ); -#endif - printf("============================== DEVICE FEATURE ENABLE/DISABLE COMMANDS =====\n\n"); -#ifdef HAVE_GETOPT_LONG - printf( -" -s VALUE, --smart=VALUE\n" -" Enable/disable SMART on device (on/off)\n\n" -" -o VALUE, --offlineauto=VALUE (ATA)\n" -" Enable/disable automatic offline testing on device (on/off)\n\n" -" -S VALUE, --saveauto=VALUE (ATA)\n" -" Enable/disable Attribute autosave on device (on/off)\n\n" - ); -#else - printf( -" -s VALUE Enable/disable SMART on device (on/off)\n" -" -o VALUE Enable/disable device automatic offline testing (on/off) (ATA)\n" -" -S VALUE Enable/disable device Attribute autosave (on/off) (ATA)\n\n" - ); -#endif - printf("======================================= READ AND DISPLAY DATA OPTIONS =====\n\n"); -#ifdef HAVE_GETOPT_LONG - printf( -" -H, --health\n" -" Show device SMART health status\n\n" -" -c, --capabilities (ATA)\n" -" Show device SMART capabilities\n\n" -" -A, --attributes (ATA)\n" -" Show device SMART vendor-specific Attributes and values\n\n" -" -l TYPE, --log=TYPE\n" -" Show device log. Type is one of: error, selftest\n\n" -" -v N,OPTION , --vendorattribute=N,OPTION (ATA)\n" -" Set display OPTION for vendor Attribute N (see man page)\n\n" -" -F TYPE, --firmwarebug=TYPE (ATA)\n" -" Use firmware bug workaround. Type is one of: none, samsung\n\n" -" -P TYPE, --presets=TYPE (ATA)\n" -" Drive-specific presets: use, ignore, show, showall\n\n" - ); -#else - printf( -" -H Show device SMART health status\n" -" -c Show device SMART capabilities (ATA)\n" -" -A Show device SMART vendor-specific Attributes and values (ATA)\n" -" -l TYPE Show device log. Type is one of: error, selftest\n" -" -v N,OPT Set display OPTion for vendor Attribute N (see man page) (ATA)\n" -" -F TYPE Use firmware bug workaround. Type is one of: none, samsung(ATA)\n" -" -P TYPE Drive-specific presets: use, ignore, show, showall (ATA)\n\n" - ); -#endif - printf("============================================ DEVICE SELF-TEST OPTIONS =====\n\n"); -#ifdef HAVE_GETOPT_LONG - printf( -" -t TEST, --test=TEST\n" -" Run test on device. TEST is one of: offline, short, long\n\n" -" -C, --captive\n" -" With -t, performs test in captive mode (short/long only)\n\n" -" -X, --abort\n" -" Abort any non-captive test on device\n\n" -); -#else - printf( -" -t TEST Run test on device. TEST is one of: offline, short, long \n" -" -C With -t, performs test in captive mode (short/long only) \n" -" -X Abort any non-captive test \n\n" - ); -#endif - printf("=================================================== SMARTCTL EXAMPLES =====\n\n"); -#ifdef HAVE_GETOPT_LONG - printf( -" smartctl -a /dev/hda (Prints all SMART information)\n\n" -" smartctl --smart=on --offlineauto=on --saveauto=on /dev/hda\n" -" (Enables SMART on first disk)\n\n" -" smartctl -t long /dev/hda (Executes extended disk self-test)\n\n" -" smartctl --attributes --log=selftest --quietmode=errorsonly /dev/hda\n" -" (Prints Self-Test & Attribute errors)\n" - ); -#else - printf( -" smartctl -a /dev/hda (Prints all SMART information)\n" -" smartctl -s on -o on -S on /dev/hda (Enables SMART on first disk)\n" -" smartctl -t long /dev/hda (Executes extended disk self-test)\n" -" smartctl -A -l selftest -q errorsonly /dev/hda\n" -" (Prints Self-Test & Attribute errors)\n" - ); -#endif -} - -/* Returns a pointer to a static string containing a formatted list of the valid - arguments to the option opt or NULL on failure. */ -const char *getvalidarglist(char opt) { - static char *v_list = NULL; - char *s; - - switch (opt) { - case 'q': - return "errorsonly, silent"; - case 'd': - return "ata, scsi"; - case 'T': - return "normal, conservative, permissive"; - case 'b': - return "warn, exit, ignore"; - case 'r': - return "ioctl[,N], ataioctl[,N], scsiioctl[,N]"; - case 's': - case 'o': - case 'S': - return "on, off"; - case 'l': - return "error, selftest, directory"; - case 'v': - if (v_list) - return v_list; - if (!(s = create_vendor_attribute_arg_list())) - return NULL; - // Allocate space for tab + "help" + newline + s + terminating 0 - v_list = (char *)malloc(7+strlen(s)); - sprintf(v_list, "\thelp\n%s", s); - free(s); - return v_list; - case 'P': - return "use, ignore, show, showall"; - case 't': - return "offline, short, long"; - case 'F': - return "none, samsung"; - default: - return NULL; - } -} - -/* Prints the message "=======> VALID ARGUMENTS ARE: <LIST> <=======\n", where - <LIST> is the list of valid arguments for option opt. */ -void printvalidarglistmessage(char opt) { - const char *s; - char separator; - - if (!(s = getvalidarglist(opt))) { - pout("Error whilst constructing argument list for option %c", opt); - return; - } - - // getvalidarglist() might produce a multiline or single line string. We - // need to figure out which to get the formatting right. - separator = strchr(s, '\n') ? '\n' : ' '; - - pout("=======> VALID ARGUMENTS ARE:%c%s%c<=======\n", separator, (char *)s, - separator); -} - -unsigned char tryata=0,tryscsi=0; - -/* Takes command options and sets features to be run */ -void ParseOpts (int argc, char** argv){ - int optchar; - int badarg; - int captive; - extern char *optarg; - extern int optopt, optind, opterr; - // Please update getvalidarglist() if you edit shortopts - const char *shortopts = "h?Vq:d:T:b:r:s:o:S:HcAl:iav:P:t:CXF:"; -#ifdef HAVE_GETOPT_LONG - char *arg; - // Please update getvalidarglist() if you edit longopts - struct option longopts[] = { - { "help", no_argument, 0, 'h' }, - { "usage", no_argument, 0, 'h' }, - { "version", no_argument, 0, 'V' }, - { "copyright", no_argument, 0, 'V' }, - { "license", no_argument, 0, 'V' }, - { "quietmode", required_argument, 0, 'q' }, - { "device", required_argument, 0, 'd' }, - { "tolerance", required_argument, 0, 'T' }, - { "badsum", required_argument, 0, 'b' }, - { "report", required_argument, 0, 'r' }, - { "smart", required_argument, 0, 's' }, - { "offlineauto", required_argument, 0, 'o' }, - { "saveauto", required_argument, 0, 'S' }, - { "health", no_argument, 0, 'H' }, - { "capabilities", no_argument, 0, 'c' }, - { "attributes", no_argument, 0, 'A' }, - { "log", required_argument, 0, 'l' }, - { "info", no_argument, 0, 'i' }, - { "all", no_argument, 0, 'a' }, - { "vendorattribute", required_argument, 0, 'v' }, - { "presets", required_argument, 0, 'P' }, - { "test", required_argument, 0, 't' }, - { "captive", no_argument, 0, 'C' }, - { "abort", no_argument, 0, 'X' }, - { "firmwarebug", required_argument, 0, 'F' }, - { 0, 0, 0, 0 } - }; -#endif - - memset(con,0,sizeof(*con)); - con->testcase=-1; - opterr=optopt=0; - badarg = captive = FALSE; - - // This miserable construction is needed to get emacs to do proper indenting. Sorry! - while (-1 != (optchar = -#ifdef HAVE_GETOPT_LONG - getopt_long(argc, argv, shortopts, longopts, NULL) -#else - getopt(argc, argv, shortopts) -#endif - )){ - switch (optchar){ - case 'V': - con->veryquietmode=FALSE; - printslogan(); - printcopy(); - exit(0); - break; - case 'q': - if (!strcmp(optarg,"errorsonly")) { - con->quietmode = TRUE; - con->veryquietmode = FALSE; - } else if (!strcmp(optarg,"silent")) { - con->veryquietmode = TRUE; - con->quietmode = TRUE; - } else { - badarg = TRUE; - } - break; - case 'd': - if (!strcmp(optarg,"ata")) { - tryata = TRUE; - tryscsi = FALSE; - } else if (!strcmp(optarg,"scsi")) { - tryata = FALSE; - tryscsi = TRUE; - } else { - badarg = TRUE; - } - break; - case 'T': - if (!strcmp(optarg,"normal")) { - con->conservative = FALSE; - con->permissive = FALSE; - } else if (!strcmp(optarg,"conservative")) { - con->conservative = TRUE; - con->permissive = FALSE; - } else if (!strcmp(optarg,"permissive")) { - con->permissive = TRUE; - con->conservative = FALSE; - } else { - badarg = TRUE; - } - break; - case 'b': - if (!strcmp(optarg,"warn")) { - con->checksumfail = FALSE; - con->checksumignore = FALSE; - } else if (!strcmp(optarg,"exit")) { - con->checksumfail = TRUE; - con->checksumignore = FALSE; - } else if (!strcmp(optarg,"ignore")) { - con->checksumignore = TRUE; - con->checksumfail = FALSE; - } else { - badarg = TRUE; - } - break; - case 'r': - { - int i; - char *s; - - // split_report_arg() may modify its first argument string, so use a - // copy of optarg in case we want optarg for an error message. - if (!(s = strdup(optarg))) { - con->veryquietmode = FALSE; - pout("Can't allocate memory to copy argument to -r option" - " - exiting\n"); - exit(FAILCMD); - } - if (split_report_arg(s, &i)) { - badarg = TRUE; - } else if (!strcmp(s,"ioctl")) { - con->reportataioctl = con->reportscsiioctl = i; - } else if (!strcmp(s,"ataioctl")) { - con->reportataioctl = i; - } else if (!strcmp(s,"scsiioctl")) { - con->reportscsiioctl = i; - } else { - badarg = TRUE; - } - free(s); - } - break; - case 's': - if (!strcmp(optarg,"on")) { - con->smartenable = TRUE; - con->smartdisable = FALSE; - } else if (!strcmp(optarg,"off")) { - con->smartdisable = TRUE; - con->smartenable = FALSE; - } else { - badarg = TRUE; - } - break; - case 'o': - if (!strcmp(optarg,"on")) { - con->smartautoofflineenable = TRUE; - con->smartautoofflinedisable = FALSE; - } else if (!strcmp(optarg,"off")) { - con->smartautoofflinedisable = TRUE; - con->smartautoofflineenable = FALSE; - } else { - badarg = TRUE; - } - break; - case 'S': - if (!strcmp(optarg,"on")) { - con->smartautosaveenable = TRUE; - con->smartautosavedisable = FALSE; - } else if (!strcmp(optarg,"off")) { - con->smartautosavedisable = TRUE; - con->smartautosaveenable = FALSE; - } else { - badarg = TRUE; - } - break; - case 'H': - con->checksmart = TRUE; - break; - case 'F': - if (!strcmp(optarg,"none")) { - con->fixfirmwarebug = FIX_NONE; - } else if (!strcmp(optarg,"samsung")) { - con->fixfirmwarebug = FIX_SAMSUNG; - } else { - badarg = TRUE; - } - break; - case 'c': - con->generalsmartvalues = TRUE; - break; - case 'A': - con->smartvendorattrib = TRUE; - break; - case 'l': - if (!strcmp(optarg,"error")) { - con->smarterrorlog = TRUE; - } else if (!strcmp(optarg,"selftest")) { - con->smartselftestlog = TRUE; - } else if (!strcmp(optarg,"directory")) { - con->smartlogdirectory = TRUE; - } else { - badarg = TRUE; - } - break; - case 'i': - con->driveinfo = TRUE; - break; - case 'a': - con->driveinfo = TRUE; - con->checksmart = TRUE; - con->generalsmartvalues = TRUE; - con->smartvendorattrib = TRUE; - con->smarterrorlog = TRUE; - con->smartselftestlog = TRUE; - break; - case 'v': - // parse vendor-specific definitions of attributes - if (!strcmp(optarg,"help")) { - char *s; - con->veryquietmode=FALSE; - printslogan(); - if (!(s = create_vendor_attribute_arg_list())) { - pout("Insufficient memory to construct argument list\n"); - exit(FAILCMD); - } - pout("The valid arguments to -v are:\n\thelp\n%s\n", s); - free(s); - exit(0); - } - if (parse_attribute_def(optarg, con->attributedefs)) - badarg = TRUE; - break; - case 'P': - if (!strcmp(optarg, "use")) { - con->ignorepresets = FALSE; - } else if (!strcmp(optarg, "ignore")) { - con->ignorepresets = TRUE; - } else if (!strcmp(optarg, "show")) { - con->showpresets = TRUE; - } else if (!strcmp(optarg, "showall")) { - showallpresets(); - exit(0); - } else { - badarg = TRUE; - } - break; - case 't': - if (!strcmp(optarg,"offline")) { - con->smartexeoffimmediate = TRUE; - con->testcase = OFFLINE_FULL_SCAN; - } else if (!strcmp(optarg,"short")) { - con->smartshortselftest = TRUE; - con->testcase = SHORT_SELF_TEST; - } else if (!strcmp(optarg,"long")) { - con->smartextendselftest = TRUE; - con->testcase = EXTEND_SELF_TEST; - } else { - badarg = TRUE; - } - break; - case 'C': - captive = TRUE; - break; - case 'X': - con->smartselftestabort = TRUE; - con->testcase = ABORT_SELF_TEST; - break; - case 'h': - case '?': - default: - con->veryquietmode=FALSE; - printslogan(); -#ifdef HAVE_GETOPT_LONG - // Point arg to the argument in which this option was found. - arg = argv[optind-1]; - // Check whether the option is a long option that doesn't map to -h. - if (arg[1] == '-' && optchar != 'h') { - // Iff optopt holds a valid option then argument must be missing. - if (optopt && (strchr(shortopts, optopt) != NULL)) { - pout("=======> ARGUMENT REQUIRED FOR OPTION: %s <=======\n", arg+2); - printvalidarglistmessage(optopt); - } else - pout("=======> UNRECOGNIZED OPTION: %s <=======\n",arg+2); - pout("\nUse smartctl --help to get a usage summary\n\n"); - exit(FAILCMD); - } -#endif - if (optopt) { - // Iff optopt holds a valid option then argument must be missing. - if (strchr(shortopts, optopt) != NULL) { - pout("=======> ARGUMENT REQUIRED FOR OPTION: %c <=======\n", optopt); - printvalidarglistmessage(optopt); - } else - pout("=======> UNRECOGNIZED OPTION: %c <=======\n",optopt); - pout("\nUse smartctl -h to get a usage summary\n\n"); - exit(FAILCMD); - } - Usage(); - exit(0); - } // closes switch statement to process command-line options - - // Check to see if option had an unrecognized or incorrect argument. - if (badarg) { - printslogan(); - // It would be nice to print the actual option name given by the user - // here, but we just print the short form. Please fix this if you know - // a clean way to do it. - pout("=======> INVALID ARGUMENT TO -%c: %s <======= \n", optchar, optarg); - printvalidarglistmessage(optchar); - pout("\nUse smartctl -h to get a usage summary\n\n"); - exit(FAILCMD); - } - } - // At this point we have processed all command-line options. - - // Do this here, so results are independent of argument order - if (con->quietmode) - con->veryquietmode=TRUE; - - // error message if user has asked for more than one test - if (1<(con->smartexeoffimmediate+con->smartshortselftest+con->smartextendselftest+ - con->smartshortcapselftest+con->smartextendcapselftest+con->smartselftestabort)){ - con->veryquietmode=FALSE; - printslogan(); - pout("\nERROR: smartctl can only run a single test (or abort) at a time.\n"); - pout("Use smartctl -h to get a usage summary\n\n"); - exit(FAILCMD); - } - - // If captive option was used, change test type if appropriate. - if (captive && con->smartshortselftest) { - con->smartshortselftest = FALSE; - con->smartshortcapselftest = TRUE; - con->testcase = SHORT_CAPTIVE_SELF_TEST; - } else if (captive && con->smartextendselftest) { - con->smartextendselftest = FALSE; - con->smartextendcapselftest = TRUE; - con->testcase = EXTEND_CAPTIVE_SELF_TEST; - } - - // From here on, normal operations... - printslogan(); - - // Warn if the user has provided no device name - if (argc-optind<1){ - pout("ERROR: smartctl requires a device name as the final command-line argument.\n\n"); - pout("Use smartctl -h to get a usage summary\n\n"); - exit(FAILCMD); - } - - // Warn if the user has provided more than one device name - if (argc-optind>1){ - int i; - pout("ERROR: smartctl takes ONE device name as the final command-line argument.\n"); - pout("You have provided %d device names:\n",argc-optind); - for (i=0; i<argc-optind; i++) - pout("%s\n",argv[optind+i]); - pout("Use smartctl -h to get a usage summary\n\n"); - exit(FAILCMD); - } -} - -// Printing function (controlled by global con->veryquietmode) -// [From GLIBC Manual: Since the prototype doesn't specify types for -// optional arguments, in a call to a variadic function the default -// argument promotions are performed on the optional argument -// values. This means the objects of type char or short int (whether -// signed or not) are promoted to either int or unsigned int, as -// appropriate.] -void pout(char *fmt, ...){ - va_list ap; - - // initialize variable argument list - va_start(ap,fmt); - if (con->veryquietmode){ - va_end(ap); - return; - } - - // print out - vprintf(fmt,ap); - va_end(ap); - fflush(stdout); - return; -} - - -/* Main Program */ -int main (int argc, char **argv){ - int fd,retval=0; - char *device; - smartmonctrl control; - int dev_type, flags; - - // define control block for external functions - con=&control; - - // Part input arguments - ParseOpts(argc,argv); - - device = argv[argc-1]; - dev_type = guess_linux_device_type(device); - if (GUESS_DEVTYPE_SCSI == dev_type) { - flags = O_RDWR | O_NONBLOCK; - tryscsi = 1; - } else { /* treat "don't know" case as an ATA device as well */ - flags = O_RDONLY | O_NONBLOCK; - tryata = 1; - } - - // open device - SCSI devices are opened (O_RDWR | O_NONBLOCK) so the - // scsi generci device can be used (needs write permission for MODE - // SELECT command) plus O_NONBLOCK to stop open hanging if media not - // present (e.g. with st). - fd = open(device, flags); - if (fd<0) { - char errmsg[256]; - snprintf(errmsg,256,"Smartctl open device: %s failed",argv[argc-1]); - errmsg[255]='\0'; - syserror(errmsg); - return FAILDEV; - } - - // now call appropriate ATA or SCSI routine - if (tryata) - retval = ataPrintMain(fd); - else if (tryscsi) - retval = scsiPrintMain(device, fd); - else { - pout("Smartctl: specify if this is an ATA or SCSI device with the -d option.\n"); - Usage(); - return FAILCMD; - } - - return retval; -} diff --git a/sm5/smartctl.h b/sm5/smartctl.h deleted file mode 100644 index 1ef52f48a..000000000 --- a/sm5/smartctl.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * smartctl.h - * - * Home page of code is: http://smartmontools.sourceforge.net - * - * Copyright (C) 2002-3 Bruce Allen <smartmontools-support@lists.sourceforge.net> - * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org> - * - * 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 Software Foundation; either version 2, or (at your option) - * any later version. - * - * You should have received a copy of the GNU General Public License - * (for example COPYING); if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * This code was originally developed as a Senior Thesis by Michael Cornwell - * at the Concurrent Systems Laboratory (now part of the Storage Systems - * Research Center), Jack Baskin School of Engineering, University of - * California, Santa Cruz. http://ssrc.soe.ucsc.edu/ - * - */ - -#ifndef __SMARTCTL_H_ -#define __SMARTCTL_H_ - -#ifndef SMARTCTL_H_CVSID -#define SMARTCTL_H_CVSID "$Id: smartctl.h,v 1.17 2003/03/06 07:27:17 ballen4705 Exp $\n" -#endif - -/* Boolean Values */ -#define TRUE 0x01 -#define FALSE 0x00 - -// Return codes (bitmask) - -// command line did not parse -#define FAILCMD (0x01<<0) - -// device open failed or could not get identity info -#define FAILDEV (0x01<<1) -#define FAILID (0x01<<1) - -// smart command failed -#define FAILSMART (0x01<<2) - -// SMART STATUS returned FAILURE -#define FAILSTATUS (0x01<<3) - -// Attributes found <= threshold with prefail=1 -#define FAILATTR (0x01<<4) - -// SMART STATUS returned GOOD but age attributes failed or prefail -// attributes have failed in the past -#define FAILAGE (0x01<<5) - -// Device had Errors in the error log -#define FAILERR (0x01<<6) - -// Device had Errors in the self-test log -#define FAILLOG (0x01<<7) - -// Classes of SMART commands. Here 'mandatory' means "Required by the -// ATA/ATAPI-5 Specification if the device implements the S.M.A.R.T. -// command set." The 'mandatory' S.M.A.R.T. commands are: (1) -// Enable/Disable Attribute Autosave, (2) Enable/Disable S.M.A.R.T., -// and (3) S.M.A.R.T. Return Status. All others are optional. -#define OPTIONAL_CMD 1 -#define MANDATORY_CMD 2 - -#endif diff --git a/sm5/smartd.8 b/sm5/smartd.8 deleted file mode 100644 index 9b2c184f9..000000000 --- a/sm5/smartd.8 +++ /dev/null @@ -1,1248 +0,0 @@ -\# Copyright (C) 2002-3 Bruce Allen <smartmontools-support@lists.sourceforge.net> -\# -\# $Id: smartd.8,v 1.94 2003/04/23 13:19:40 guidog Exp $ -\# -\# 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 -\# Software Foundation; either version 2, or (at your option) any later -\# version. -\# -\# You should have received a copy of the GNU General Public License (for -\# example COPYING); if not, write to the Free Software Foundation, Inc., 675 -\# Mass Ave, Cambridge, MA 02139, USA. -\# -\# This code was originally developed as a Senior Thesis by Michael Cornwell -\# at the Concurrent Systems Laboratory (now part of the Storage Systems -\# Research Center), Jack Baskin School of Engineering, University of -\# California, Santa Cruz. http://ssrc.soe.ucsc.edu/ -\# -.TH SMARTD 8 "$Date: 2003/04/23 13:19:40 $" "smartmontools-5.1" -.SH NAME -smartd \- SMART Disk Monitoring Daemon -.SH SYNOPSIS -.B smartd [options] - -.SH DESCRIPTION -.B smartd -is a daemon that monitors the Self-Monitoring, Analysis and Reporting -Technology (SMART) system built into many ATA-3 and later ATA, -IDE and SCSI-3 hard drives. The purpose of SMART is to monitor -the reliability of the hard drive and predict drive failures, and to -carry out different types of drive self-tests. This version of -.B smartd -is compatible with ATA/ATAPI-5 and earlier standards (see -.B REFERENCES -below) - -.B smartd -will attempt to enable SMART monitoring on ATA devices (equivalent to -.B smartctl -s on -) and polls -these and SCSI devices every 30 minutes (configurable), logging -SMART errors and changes of SMART Attributes via the SYSLOG -interface. The default location for these SYSLOG notifications and -warnings is -.B /var/log/messages. - -.B smartd -can be configured at start-up using the file -.B /etc/smartd.conf. -Note that -.B smartd -only reads the configuration file at start-up: changes to the -configuration file take effect only after the -.B smartd -daemon is restarted. -If you send a -.B HUP -signal to -.B smartd -it will log a polite message saying that it ignores this signal and -that it has -.I not -re-read the configuration file. - -If you send a -.B USR1 -signal to -.B smartd -it will immediately check the status of the disks, and then return to -polling the disks every 30 minutes. See the -.B '\-i' -option below for additional details. - -On startup, in the absence of the configuration file -.B /etc/smartd.conf, -the -.B smartd -daemon first scans for all devices that support SMART, using -.B "/dev/hd[a-l]" -for IDE/ATA devices, and -.B "/dev/sd[a-z]" -for SCSI devices. It then monitors for -.I all -possible SMART errors (corresponding to the -.B '\-a' -Directive in the configuration file; see -.B CONFIGURATION FILE -below). Note that when there is no configuration file, and -.B smartd -scans for devices on startup, -.B warning messages may appear in SYSLOG -(by default -.B /var/log/messages) -about missing block-major-xx devices. These messages are usually -harmless. Alternatively, the configuration file can be used to exclude -non-existent devices by giving a list of devices to monitor at -start-up. - -.SH -OPTIONS -Long options are not supported on all systems. Use -.B 'smartd \-h' -to see the available options. -.TP -.B \-d, \-\-debug -Runs -.B smartd -in ""debug"" mode. In this mode, it does not -.B fork -(2) and displays status information to STDOUT. It also prints more -verbose information about what it is doing. -.TP -.B \-D, \-\-showdirectives -Prints a list (to STDOUT) of all the possible Directives which may -appear in the configuration file /etc/smartd.conf, and then exits. -These Directives are also described later in this man page. They may -appear in the configuration file following the device name. -.TP -.B \-i N, \-\-interval=N -Sets the interval between disk checks to -.I N -seconds, where -.I N -is a decimal integer. The minimum allowed value is ten and the maximum is the -largest positive integer that can be represented on your system (often 2^31-1). -The default is 1800 seconds. - -Note that the superuser can make -.B smartd -check the status of the disks at any time by sending it the -.B SIGUSR1 -signal, for example with the command: -.nf -.B kill -SIGUSR1 <pid> -.fi -where -.B <pid> -is the process id number of -.B smartd. -One may also use: -.nf -.B killall -USR1 smartd -.fi -for the same purpose. - -.TP -.B \-p NAME, \-\-pidfile=NAME -Writes pidfile -.I NAME -containing the -.B smartd -Process ID number (PID). -To avoid symlink attacks make sure the directory to which -pidfile is written is only writeable for root. Without this option, -or if the --debug option is given, no PID file is written on startup. -If -.B smartd -is killed with a maskable signal then the pidfile is removed. - -.TP -.B \-c, \-\-checkonce -Start -.B smartd -in debug mode, then register devices, then check device's SMART status -once, and then exit with zero exit status if -all of these steps worked correctly. - -This option is intended for 'distribution-writers' who -want to create automated scripts to determine whether or not to -automatically start up -.B smartd -after installing smartmontools. After starting -.B smartd -with this command-line option, the distribution's install scripts should -wait a reasonable length of time (say ten seconds). If -.B smartd -has not exited with zero status by that time, the script should send -.B smartd -a SIGTERM or SIGKILL and assume that -.B smartd -will not operate correctly on the host. Conversely, if -.B smartd -exits with zero status, then it is safe to run -.B smartd -in normal daemon mode. - -Note that if -.B smartd -is unable to monitor any devices or encounters other problems then it -will return with non-zero exit status. - -.TP -.B \-V, \-\-version, \-\-license, \-\-copyright -Prints license, copyright, and CVS version information onto -STDOUT and then exits. Please include this information if you are -reporting bugs, or have specific questions about the behavior of -.B smartd. -.TP -.B \-h, \-\-help, \-\-usage -Prints usage message to STDOUT and exits. -.TP -.B \-? -Same as -.B -h. - - -.TP -.B \-r TYPE, \-\-report=TYPE -Intended primarily to help -.B smartmontools -developers understand the behavior of -.B smartmontools -on non-conforming or poorly conforming hardware. This option reports -details of -.B smartd -transactions with the device. The option can be used multiple times. -When used just once, it shows a record of the ioctl() transactions -with the device. Whe used more than once, the detail of these ioctl() -transactions are reported in greater detail. The valid arguments to -this option are: - -.I ioctl -\- report all ioctl() transactions. - -.I ataioctl -\- report only ioctl() transactions with ATA devices. - -.I scsiioctl -\- report only ioctl() transactions with SCSI devices. - -Any argument may include a positive integer to specify the level of detail -that should be reported. The argument should be followed by a comma then -the integer with no spaces. For example, -.I ataioctl,2 -The default -level is 1, so '\-r ataioctl,1' and '\-r ataioctl' are equivalent. - - -.SH EXAMPLES - -.B -smartd -.fi -Runs the daemon in forked mode. This is the normal way to run -.B smartd. -Entries are logged to SYSLOG (by default -.B /var/log/messages.) - -.B -smartd -d -i 30 -.fi -Run in foreground (debug) mode, checking the disk status -every 30 seconds. - -.B -smartd -c -.fi -Registers devices, and checks the status of the devices exactly -once. The exit status (the bash -.B $? -variable) will be zero if all went well, and nonzero if no devices -were detected or some other problem was encountered. - -.fi -Note that -.B smartmontools -provides a start-up script in -.B /etc/rc.d/init.d/smartd -which is responsible for starting and stopping the daemon via the -normal init interface. -Using this script, you can start -.B smartd -by giving the command: -.nf -.B /etc/rc.d/init.d/smartd start -.fi -and stop it by using the command: -.nf -.B /etc/rc.d/init.d/smartd stop - -.fi -If you want -.B smartd -to start running whenever your machine is booted, this can be enabled -by using the command: -.nf -.B /sbin/chkconfig --add smartd -.fi -and disabled using the command: -.nf -.B /sbin/chkconfig --del smartd - -\# DO NOT MODIFY THIS OR THE FOLLOWING TWO LINES. THIS MATERIAL -\# IS AUTOMATICALLY INCLUDED IN THE FILE smartd.conf.5 -\# STARTINCLUDE - -.SH CONFIGURATION FILE /etc/smartd.conf -In the absence of a configuration file, -.B smartd -will try to open the 12 ATA devices -.B /dev/hd[a-l] -and the 26 SCSI devices -.B /dev/sd[a-z]. -This can be annoying if you have an ATA or SCSI device that hangs or -misbehaves when receiving SMART commands. Even if this causes no -problems, you may be annoyed by the string of error log messages about -block-major devices that can't be found, and SCSI devices that can't -be opened. - -One can avoid this problem, and gain more control over the types of -events monitored by -.B smartd, -by using the configuration file -.B /etc/smartd.conf. -This file contains a list of devices to monitor, with one device per -line. An example file is included with the -.B smartmontools -distribution. You will find this sample configuration file in -\fB/usr/share/doc/smartmontools-5.1/\fP. For security, the configuration file -should not be writable by anyone but root. The syntax of the file is as -follows: - -.IP -There should be one device listed per line, although you may have -lines that are entirely comments or white space. - -Any text following a hash sign (#) and up to the end of the line is -taken to be a comment, and ignored. - -Lines may be continued by using a backslash (\(rs) as the last -non-whitespace or non-comment item on a line. - -.PP 0 -.fi -Here is an example configuration file. It's for illustrative purposes -only; please don't copy it onto your system without reading to the end -of the -.B DIRECTIVES -Section below! - -.nf -.B ################################################ -.B # This is an example smartd startup config -.B # file /etc/smartd.conf for monitoring three -.B # ATA disks and two SCSI disks. -.B # -.nf -.B # First ATA disk on each of two interfaces: -.B # -.B \ \ /dev/hda -a -m admin@yoyodyne.com,root@localhost -.B \ \ /dev/hdc -a -I 194 -I 5 -i 12 -.B # -.nf -.B # SCSI disks. Send a TEST warning email to admin on -.B # startup. -.B # -.B \ \ /dev/sda -.B \ \ /dev/sdc -m admin@yoyodyne.com -M test -.B # -.nf -.B # Strange device. It's SCSI: -.B # -.B \ \ /dev/weird -d scsi -.B # -.nf -.B # The following line enables monitoring of the -.B # ATA Error Log and the Self-Test Error Log. -.B # It also tracks changes in both Prefailure -.B # and Usage Attributes, apart from Attributes -.B # 9, 194, and 231, and shows continued lines: -.B # -.B \ \ /dev/hdd\ -l\ error\ \(rs -.B \ \ \ \ \ \ \ \ \ \ \ -l\ selftest\ \(rs -.B \ \ \ \ \ \ \ \ \ \ \ -t\ \(rs\ \ \ \ \ \ # Attributes not tracked: -.B \ \ \ \ \ \ \ \ \ \ \ -I\ 194\ \(rs\ \ # temperature -.B \ \ \ \ \ \ \ \ \ \ \ -I\ 231\ \(rs\ \ # also temperature -.B \ \ \ \ \ \ \ \ \ \ \ -I 9\ \ \ \ \ \ # power-on hours -.B # -.B ################################################ -.fi - -.PP -.SH CONFIGURATION FILE DIRECTIVES -.PP - -If the first non-comment entry in the configuration file is the text -string -.B DEVICESCAN -in capital letters, then -.B smartd -will ignore any remaining lines in the configuration file, and will -scan for devices. -.B DEVICESCAN -may optionally be followed by Directives that will apply to all -devices that are found in the scan. Please see below for additional -details. - -.sp 2 -The following are the Directives that may appear following the device -name or -.B DEVICESCAN -on any line of the -.B /etc/smartd.conf -configuration file. Note that -.B these are NOT command-line options for -.B smartd. -The Directives below may appear in any order, following the device -name. - -.B For an ATA device, -if no Directives appear, then the device will be monitored -as if the '\-a' Directive (monitor all SMART properties) had been given. - -.B If a SCSI disk is listed, -it will be monitored at the only implemented level: roughly equivalent -to using the '\-H' option for an ATA disk. So with the exception of '\-d', '\-m', and '\-M', -the Directives below are ignored for SCSI -disks. For SCSI disks, the '\-m' Directive sends a warning email if -the SMART status indicates a disk failure or problem, or if the SCSI inquiry about disk status fails. - -.TP -.B \-d TYPE -Specifies the type of the device. This will prevent -.B smartd -from issuing SCSI commands to an ATA device and vice versa. The valid -arguments to this Directive are \fIata\fP and \fIscsi\fP. - -In the absence of this Directive, -.B smartd -will first attempt to guess the device type by looking at whether the sixth -character in the device name is an 's' or an 'h'. This will work for -device names like /dev/hda or /dev/sdb. If -.B smartd -can't guess from this sixth character, then it will simply try to -access the device using first ATA and then SCSI ioctl()s. -.TP -.B \-T TYPE -Specifies how tolerant -.B smartd -should be of SMART command failures. The valid arguments to this -Directive are: - -.I normal -\- do not try to monitor the disk if a mandatory SMART command fails, but -continue if an optional SMART command fails. This is the default. - -.I permissive -\- try to monitor the disk even if it appears to lack SMART capabilities. -This may be required for some old disks (prior to ATA-3 revision 4) that -implemented SMART before the SMART standards -were incorporated into the ATA/ATAPI Specifications. - -[Please see the -.B smartctl \-T -command-line option.] -.TP -.B \-o VALUE -Enables or disables SMART Automatic Offline Testing when -.B smartd -starts up and has no further effect. The valid arguments to this -Directive are \fIon\fP and \fIoff\fP. - -The delay between tests is vendor-specific, but is typically four hours. -[Please see the -.B smartctl \-o -command-line option.] -.TP -.B \-S VALUE -Enables or disables Attribute Autosave when -.B smartd -starts up and has no further effect. The valid arguments to this -Directive are \fIon\fP and \fIoff\fP. [Please see the -.B smartctl \-S -command-line option.] -.TP -.B \-H -Check the SMART health status of the disk. If any Prefailure -Attributes are less than or equal to their threshold values, then disk -failure is predicted in less than 24 hours, and a message at priority -.B 'CRITICAL' -will be logged to syslog. [Please see the -.B smartctl \-H -command-line option.] -.TP -.B \-l TYPE -Reports increases in the number of errors in one of the two SMART logs. The -valid arguments to this Directive are: - -.I error -\- report if that the number of ATA errors reported in the ATA Error Log has -increased since the last check. - -.I selftest -\- report if that the number of errors reported in the SMART Self-Test Log -has increased since the last check. Note that such errors will -.B only -be logged if you run self-tests on the disk (and it fails the tests!). -[Self-Tests can be run by using the -.B '\-t\ short' -and -.B '\-t\ long' -options of -.B smartctl -and the results of the testing can be observed using the -.B smartctl '\-l\ selftest' -command-line option.] - -[Please see the -.B smartctl \-l -command-line option.] -.TP -.B \-f -Check for 'failure' of any Usage Attributes. If these -Attributes are less than or equal to the threshold, it does NOT -indicate imminent disk failure. It ""indicates an advisory condition -where the usage or age of the device has exceeded its intended design -life period."" [Please see the -.B smartctl \-A -command-line option.] - -.TP -.B \-m ADD -Send a warning email to the email address -.B ADD -if the '\-H', '\-l', or '\-f' Directives detect a failure or a new -error, or is a SMART command to the disk fails. This Directive only -works in conjunction with these other Directives (or with the -equivalent default '\-a' Directive). - -To prevent your email in-box from getting filled up with warning -messages, by default only a single warning will be sent for each of -the enabled test types, '\-H', '\-l', or '\-f', even if more than one -failure or error is detected or if the failure or error persists. -[This behavior can be modified; see the '\-M' Directive below.] - -To send email to more than one user, please use the following form for -the address: -.B user1@add1,user2@add2,...,userN@addN -(with no spaces). - -To test that email is being sent correctly, use the '\-M test' -Directive described below to send one test email message on -.B smartd -startup. - -By default, email is sent using the system -.B mail -command. In order that -.B smartd -find the mail command (normally /bin/mail) an executable named -.B 'mail' -must be in the path of the shell or environment from which -.B smartd -was started. If you wish to specify an explicit path to the mail -executable (for example /usr/local/bin/mail) or a custom script to -run, please use the '\-M exec' Directive below. - -Note that there is a special argument -.B <nomailer> -which can be given to the '\-m' Directive in conjunction with the '\-M -exec' Directive. Please see below for an explanation of its effect. - -.TP -.B \-M TYPE -These Directives modify the behavior of the -.B smartd -email warnings enabled with the '\-m' email Directive described above. -These '\-M' Directives only work in conjunction with the '\-m' -Directive and can not be used without it. - -Multiple \-M Directives may be given. If conflicting \-M Directives -are given (example: \-M once \-M daily) then the final one (in the -example, \-M daily) is used. - -The valid arguments to the \-M Directive are: - -.I once -\- send only one warning email for each type of disk problem detected. This -is the default. - -.I daily -\- send additional warning reminder emails, once per day, for each type -of disk problem detected. - -.I diminishing -\- send additional warning reminder emails, after a one-day interval, -then a two-day interval, then a four-day interval, and so on for each -type of disk problem detected. Each interval is twice as long as the -previous interval. - -.I test -\- send a single test email -immediately upon -.B smartd -startup. This allows one to verify that any email is correctly delivered. - -.I exec PATH -\- run the executable PATH instead of the default mail command, when -.B smartd -needs to send email. PATH must point to an executable binary file or -script. - -By setting PATH to point to a customized script, you can make -.B smartd -perform useful tricks when a disk problem is detected (beeping the -console, shutting down the machine, broadcasting warnings to all -logged-in users, etc.) But please be careful. -.B smartd -will -.B block -until the executable PATH returns, so if your executable hangs, then -.B smartd -will also hang. Some sample scripts are included in -/usr/share/doc/smartmontools-5.1/examplescripts/. - -The return status of the executable is recorded by -.B smartd -in SYSLOG, but the executable's STDOUT and STDERR are directed to -/dev/null, so if you wish to leave some other record behind, the -executable must send mail or write to a file or device. - -Before running the executable, -.B smartd -sets a number of environment variables. These environment variables -may be used to control the executable's behavior. The environment -variables exported by -.B smartd -are: -.nf -.fi -.B SMARTD_MAILER -is set to the argument of -M exec, if present or else to 'mail' -(examples: /bin/mail, mail). -.nf -.fi -.B SMARTD_DEVICE -is set to the device path (examples: /dev/hda, /dev/sdb). -.nf -.fi -.B SMARTD_DEVICETYPE -is set to the device type (possible values: ata, scsi). -.nf -.fi -.B SMARTD_FAILTYPE -gives the reason for the warning or message email. The possible values that -it takes, and their significance, are: -.I emailtest -(this is an email test message); -.I health -(the SMART health status indicates imminent failure); -.I usage -(a usage Attribute has failed); -.I selftest -(the number of self-test failures has increased); -.I errorcount -(the number of errors in the ATA error log has increased); -.I FAILEDhealthcheck -(the SMART health status command failed); -.I FAILEDreadsmartdata -(the command to read SMART Attribute data failed); -.I FAILEDreadsmarterrorlog -(the command to read the SMART error log failed); -.I FAILEDreadsmartsefltestlog -(the command to read the SMART self-test log failed); abd -.I FAILEDopendevice -(the open() command to the device failed). -.nf -.fi -.B SMARTD_ADDRESS -is set to the address argument ADD of the '\-m' Directive, unless ADD -is -.B <nomailer>. -This is a comma-delineated list of email addresses (example: -admin@yoyodyne.com). -.nf -.fi -.B SMARTD_MESSAGE -is set to the warning email message string from -.B smartd. -This message string contains space characters and is NOT quoted. So to -use $SMARTD_MESSAGE in a bash script you should probably enclose it in -double quotes. -.nf -.fi -.B SMARTD_TFIRST -is a text string giving the time and date at which the first problem -of this type was reported. This text string contains space characters -and no newlines, and is NOT quoted. For example: -.nf -.fi -Sun Feb 9 14:58:19 2003 CST -.nf -.fi -.B SMARTD_TFIRSTEPOCH -is an integer, which is the unix epoch (number of seconds since Jan 1, -1970) for -.B SMARTD_TFIRST. - -The shell which is used to run PATH is system-dependent. For vanilla -linux/glibc it's bash. For other systems, the man page for system (3) -should say what shell is used. - -If the '\-m ADD' Directive is given with a normal address argument, -then the executable pointed to by PATH will be run in a shell with -STDIN receiving the body of the email message, and with the same -command-line arguments: -.nf --s \(dq$SMARTD_SUBJECT\(dq $SMARTD_ADDRESS -.fi -that would normally be provided to 'mail'. Examples include: -.nf -.B -m user@home -M exec /bin/mail -.B -m admin@work -M exec /usr/local/bin/mailto -.B -m root -M exec /Example_1/bash/script/below -.fi - -If the '\-m ADD' Directive is given with the special address argument -.B <nomailer> -then the executable pointed to by PATH is run in a shell with -.B no -STDIN and -.B no -command-line arguments, for example: -.nf -.B -m <nomailer> -M exec /Example_2/bash/script/below -.fi - -Some EXAMPLES of scripts that can be used with the '\-M exec' -Directive are given below. Some sample scripts are also included in -/usr/share/doc/smartmontools-5.1/examplescripts/. - -.TP -.B \-p -Report anytime that a Prefail Attribute has changed -its value since the last check, 30 minutes ago. [Please see the -.B smartctl \-A -command-line option.] -.TP -.B \-u -Report anytime that a Usage Attribute has changed its value -since the last check, 30 minutes ago. [Please see the -.B smartctl \-A -command-line option.] -.TP -.B \-t -Equivalent to turning on the two previous flags '\-p' and '\-u'. -Tracks changes in -.I all -device Attributes (both Prefailure and Usage). [Please see the -.B smartctl \-A -command-line option.] -.TP -.B \-i ID -Ignore device Attribute number -.B ID -when checking for failure of Usage Attributes. -.B ID -must be a decimal integer in the range from 1 to 255. This Directive -modifies the behavior of the '\-f' Directive and has no effect without -it. - -This is useful, for example, if you have a very old disk and don't want to keep -getting messages about the hours-on-lifetime Attribute (usually Attribute 9) -failing. This Directive may appear multiple times for a single device, if you -want to ignore multiple Attributes. -.TP -.B \-I ID -Ignore device Attribute -.B ID -when tracking changes in the Attribute values. -.B ID -must be a decimal integer in the range from 1 to 255. This Directive modifies -the behavior of the '\-p', '\-u', and '\-t' tracking Directives and has no effect -without one of them. - -This is useful, for example, if one of the device Attributes is the disk -temperature (usually Attribute 194 or 231). It's annoying to get reports -each time the temperature changes. This Directive may appear multiple -times for a single device, if you want to ignore multiple Attributes. -.TP -.B \-r ID -When tracking, report the -.I Raw -value of Attribute -.B ID -along with its (normally reported) -.I Normalized -value. -.B ID -must be a decimal integer in the range from 1 to 255. This Directive modifies -the behavior of the '\-p', '\-u', and '\-t' tracking Directives and has no effect -without one of them. This Directive may be given multiple times. - -A common use of this Directive is to track the device Temperature -(often ID=194 or 231). - -.TP -.B \-R ID -When tracking, -report whenever the -.I Raw -value of Attribute -.B ID -changes. (Normally -.B smartd -only tracks/reports changes of the -.I Normalized -Attribute values.) -.B ID -must be a decimal integer in the range from 1 to 255. This Directive -modifies the behavior of the '\-p', '\-u', and '\-t' tracking Directives and -has no effect without one of them. This Directive may be given -multiple times. - -If this Directive is given, it automatically implies the '\-r' -Directive for the same Attribute, so that the Raw value of the -Attribute is reported. - -A common use of this Directive is to track the device Temperature -(often ID=194 or 231). It is also useful for understanding how -different types of system behavior affects the values of certain -Attributes. - -.TP -.B \-F TYPE, \-\-firmwarebug=TYPE -Modifies the behavior of -.B smartctl -to compensate for some known and understood device firmware bug. The -valid arguments to this option are: - -.I none -Assume that the device firmware obeys the ATA specifications. This is -the default. - -.I samsung -In some Samsung disks (example: model SV4012H Firmware Version: -RM100-08) some of the two- and four-byte quantities in the SMART data -structures are byte-swapped (relative to the ATA specification). -Enabling this option tells -.B smartctl -to evaluate these quantities in byte-reversed order. Some signs that -your disk needs this option are (1) no self-test log printed, even -though you have run self-tests; (2) very large numbers of ATA errors -reported in the ATA erorr log; (3) strange and impossible values for -the ATA error log timestamps. - -[Please see the -.B smartctl \-F -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: - -.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 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. - -.I 200,writeerrorcount -\- Raw Attribute number 200 is the Write Error 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: -http://coredump.free.fr/linux/hddtemp.db - -.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 \-P TYPE -Specifies whether -.B smartd -should use any preset options that are available for this drive. The -valid arguments to this Directive are: - -.I use -\- use any presets that are available for this drive. This is the default. - -.I ignore -\- do not use any presets for this drive. - -.I show -\- show the presets listed for this drive in the database. - -.I showall -\- show the presets that are available for all drives and then exit. - -[Please see the -.B smartctl \-P -command-line option.] - -.TP -.B \-a -Equivalent to turning on all of the following Directives: -.B '\-H' -to check the SMART health status, -.B '\-f' -to report failures of Usage (rather than Prefail) Attributes, -.B '\-t' -to track changes in both Prefailure and Usage Attributes, -.B '\-l\ selftest' -to report increases in the number of Self-Test Log errors, and -.B '\-l\ error' -to report increases in the number of ATA errors. - -Note that \-a is the default for ATA devices. If none of these other -Directives is given, then \-a is assumed. - -.TP -.B # -Comment: ignore the remainder of the line. -.TP -.B \(rs -Continuation character: if this is the last non-white or non-comment -character on a line, then the following line is a continuation of the current -one. -.PP -If you are not sure which Directives to use, I suggest experimenting -for a few minutes with -.B smartctl -to see what SMART functionality your disk(s) support(s). If you do -not like voluminous syslog messages, a good choice of -.B smartd -configuration file Directives might be: -.nf -.B \-H \-l\ selftest \-l\ error \-f. -.fi -If you want more frequent information, use: -.B -a. - -.TP -.B ADDITIONAL DETAILS ABOUT DEVICESCAN -If the first non-comment entry in the configuration file is the text -string -.B DEVICESCAN -in capital letters, then -.B smartd -will ignore any remaining lines in the configuration file, and will -scan for devices. - -If -.B DEVICESCAN -is not followed by any Directives, then smartd will scan for both ATA -and SCSI devices, and will monitor all possible SMART properties of -any devices that are found. - -.B DEVICESCAN -may optionally be followed by any valid Directives, which will be -applied to all devices that are found in the scan. For example -.nf -.B DEVICESCAN -m root@yoyodyne.com -.fi -will scan for all devices, and then monitor them. It will send one -email warning per device for any problems that are found. -.nf -.B DEVICESCAN -d ata -m root@yoyodyne.com -.fi -will do the same, but restricts the scan to ATA devices only. -.nf -.B DEVICESCAN -H -d ata -m root@yoyodyne.com -.fi -will do the same, but only monitors the SMART health status of the -devices, (rather than the default \-a, which monitors all SMART -properties). - -.TP -.B EXAMPLES OF SHELL SCRIPTS FOR '\-M exec' -These are two examples of shell scripts that can be used with the '\-M -exec PATH' Directive described previously. The paths to these scripts -and similar executables is the PATH argument to the '\-M exec PATH' -Directive. - -Example 1: This script is for use with '\-m ADDRESS -M exec PATH'. It appends -the output of -.B smartctl -a -to the output of the smartd email warning message and sends it to ADDRESS. - -.nf -.B #! /bin/bash - -.B # Save the email message (STDIN) to a file: -.B cat > /root/msg - -.B # Append the output of smartctl -a to the message: -.B /usr/sbin/smartctl -a $SMARTD_DEVICE >> /root/msg - -.B # Now email the message to the user at address ADD: -.B /bin/mail -s \(dq$SMARTD_SUBJECT\(dq $SMARTD_ADDRESS < /root/msg -.fi - -Example 2: This script is for use with '\-m <nomailer> \-M exec -PATH'. It warns all users about a disk problem, waits 30 seconds, and -then powers down the machine. - -.nf -.B #! /bin/bash - -.B # Warn all users of a problem -.B wall 'Problem detected with disk: ' $SMARTD_DEVICE -.B wall 'Warning message from smartd is: ' \(dq$SMARTD_MESSAGE\(dq -.B wall 'Shutting down machine in 30 seconds... ' - -.B # Wait half a minute -.B sleep 30 - -.B # Power down the machine -.B /usr/sbin/shutdown -hf now -.fi - -Some example scripts are distributed with the smartmontools package, -in /usr/share/doc/smartmontools-5.1/examplescripts/. - -Please note that these scripts typically run as root, so any files -that they read/write should not be writable by ordinary users or -reside in directories like /tmp that are writable by ordinary users -and may expose your system to symlink attacks. - -\# ENDINCLUDE -\# DO NOT MODIFY THIS OR PREVIOUS/NEXT LINES. THIS DEFINES THE -\# END OF THE INCLUDE SECTION FOR smartd.conf.5 - -.SH NOTES -.B smartd -will make log entries at loglevel -.B LOG_INFO -if the Normalized SMART Attribute values have changed, as reported using the -.B '\-t', '\-p', -or -.B '\-u' -Directives. For example: -.nf -.B 'Device: /dev/hda, SMART Attribute: 194 Temperature_Celsius changed from 94 to 93' -.fi -Note that in this message, the value given is the 'Normalized' not the 'Raw' -Attribute value (the disk temperature in this case is about 22 -Celsius). The -.B '-R' -and -.B '-r' -Directives modify this behavior, so that the information is printed -with the Raw values as well, for example: -.nf -.B 'Device: /dev/hda, SMART Attribute: 194 Temperature_Celsius changed from 94 [Raw 22] to 93 [Raw 23]' -.fi -Here the Raw values are the actual disk temperatures in Celsius. The -way in which the Raw values are printed, and the names under which the -Attributes are reported, is governed by the various -.B \'-v Num,Description' -Directives described previously. - -Please see the -.B smartctl -manual page for further explanation of the differences between -Normalized and Raw Attribute values. - -.B smartd -will make log entries at loglevel -.B LOG_CRIT -if a SMART Attribute has failed, for example: -.nf -.B 'Device: /dev/hdc, Failed SMART Attribute: 5 Reallocated_Sector_Ct' -.fi - This loglevel is used for reporting enabled by the -.B '\-H', \-f', '\-l\ selftest', -and -.B '\-l\ error' -Directives. Entries reporting failure of SMART Prefailure Attributes -should not be ignored: they mean that the disk is failing. Use the -.B smartctl -utility to investigate. - -.SH RETURN VALUES -The return value (exit status) of -.B smartd -can have the following values: -.TP -.B 0: -Daemon startup successful. -.TP -.B 1: -Commandline did not parse. -.TP -.B 2: -There was a problem opening or parsing \fB/etc/smartd.conf\fP. -.TP -.B 3: -Forking the daemon failed. -.TP -.B 4: -Couldn't create PID file. -.TP -.B 8: -.B smartd -ran out of memory during startup. -.TP -.B 9: -A compile time constant of\fB smartd\fP was too small. This can be caused by an -excessive number of disks, or by lines in \fB /etc/smartd.conf\fP that are too long. -Please report this problem to \fB smartmontools-support@lists.sourceforge.net\fP. -.TP -.B 16: -A device specified in -.B /etc/smartd.conf -can't be monitored. -.TP -.B 17: -.B smartd -didn't find any device to monitor. -.TP -.B 254: -.B smartd -received a fatal signal. - -.PP -.SH AUTHOR -Bruce Allen -.B smartmontools-support@lists.sourceforge.net -.fi -University of Wisconsin - Milwaukee Physics Department - -.PP -.SH CREDITS -.fi -This code was derived from the smartsuite package, written by Michael -Cornwell, and from the previous ucsc smartsuite package. It extends -these to cover ATA-5 disks. This code was originally developed as a -Senior Thesis by Michael Cornwell at the Concurrent Systems Laboratory -(now part of the Storage Systems Research Center), Jack Baskin School -of Engineering, University of California, Santa -Cruz. http://ssrc.soe.ucsc.edu/. -.SH -HOME PAGE FOR SMARTMONTOOLS: -.fi -Please see the following web site for updates, further documentation, bug -reports and patches: -.nf -.B -http://smartmontools.sourceforge.net/ - -.SH -SEE ALSO: -.B smartd.conf -(5), -.B smartctl -(8), -.B syslogd -(8) -.SH -REFERENCES FOR SMART -.fi -If you would like to understand better how SMART works, and what -it does, a good place to start is Section 8.41 of the 'AT -Attachment with Packet Interface-5' (ATA/ATAPI-5) specification. This -documents the SMART functionality which the -.B smartmontools -utilities provide access to. You can find Revision 1 of this document -at: -.nf -.B -http://www.t13.org/project/d1321r1c.pdf -.fi -Future versions of the specifications (ATA/ATAPI-6 and ATA/ATAPI-7), -and later revisions (2, 3) of the ATA/ATAPI-5 specification are -available from: -.nf -.B -http://www.t13.org/#FTP_site - -.fi -The functioning of SMART is also described by the SFF-8035i -revision 2 specification. This is a publication of the Small Form -Factors (SFF) Committee, and can be obtained from: -.TP -\ -SFF Committee -.nf -14426 Black Walnut Ct. -.nf -Saratoga, CA 95070, USA -.nf -SFF FaxAccess: +01 408-741-1600 -.nf -Ph: +01 408-867-6630 -.nf -Fax: +01 408-867-2115 -.nf -E-Mail: 250-1752@mcimail.com. -.PP -Please let us know if there is an on\-line source for this document. - -.SH -CVS ID OF THIS PAGE: -$Id: smartd.8,v 1.94 2003/04/23 13:19:40 guidog Exp $ diff --git a/sm5/smartd.c b/sm5/smartd.c deleted file mode 100644 index 4f9fe0cb6..000000000 --- a/sm5/smartd.c +++ /dev/null @@ -1,2180 +0,0 @@ -/* - * Home page of code is: http://smartmontools.sourceforge.net - * - * Copyright (C) 2002-3 Bruce Allen <smartmontools-support@lists.sourceforge.net> - * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org> - * - * 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 Software Foundation; either version 2, or (at your option) - * any later version. - * - * You should have received a copy of the GNU General Public License - * (for example COPYING); if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * This code was originally developed as a Senior Thesis by Michael Cornwell - * at the Concurrent Systems Laboratory (now part of the Storage Systems - * Research Center), Jack Baskin School of Engineering, University of - * California, Santa Cruz. http://ssrc.soe.ucsc.edu/ - * - */ - -#define _GNU_SOURCE -#include <stdio.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/wait.h> -#include <unistd.h> -#include <fcntl.h> -#include <string.h> -#include <linux/hdreg.h> -#include <syslog.h> -#include <stdarg.h> -#include <signal.h> -#include <stdlib.h> -#include <errno.h> -#include <string.h> -#include <time.h> -#include <limits.h> -#ifdef HAVE_GETOPT_H -#include <getopt.h> -#endif -#include "atacmds.h" -#include "ataprint.h" -#include "extern.h" -#include "knowndrives.h" -#include "scsicmds.h" -#include "smartd.h" -#include "utility.h" - -extern const char *atacmds_c_cvsid, *ataprint_c_cvsid, *knowndrives_c_cvsid, *scsicmds_c_cvsid, *utility_c_cvsid; -const char *smartd_c_cvsid="$Id: smartd.c,v 1.158 2003/04/26 11:20:22 ballen4705 Exp $" -ATACMDS_H_CVSID ATAPRINT_H_CVSID EXTERN_H_CVSID KNOWNDRIVES_H_CVSID SCSICMDS_H_CVSID SMARTD_H_CVSID UTILITY_H_CVSID; - -// Forward declaration -const char *getvalidarglist(char opt); - -// global variable used for control of printing, passing arguments, etc. -smartmonctrl *con=NULL; - -// Two other globals -- number of ATA and SCSI devices being monitored -int numatadevices=0; -int numscsidevices=0; - -// How long to sleep between checks. Handy as global variable for -// debugging -int checktime=CHECKTIME; - -// name of PID file (== NULL if no pid_file is used) -char* pid_file=NULL; - -// If set, we should exit after checking all disks once -int checkonce=0; - -// Needed to interrupt sleep when catching SIGUSR1. Unix Gurus: I -// know that this can be done better. Please tell me how -- use email -// address for Bruce Allen at the top of this file. Search for -// "sleeptime" to see what I am doing. -volatile int sleeptime=CHECKTIME; - -// Interrupt sleep if we get a SIGUSR1. Unix Gurus: I know that this -// can be done better. Please tell me how -- use email address for -// Bruce Allen at the top of this file. Search for "sleeptime" to see -// what I am doing. -void sleephandler(int sig){ - int oldsleeptime=sleeptime; - sleeptime=0; - printout(LOG_CRIT,"Signal USR1 - checking devices now rather than in %d seconds.\n",oldsleeptime<0?0:oldsleeptime); - return; -} - -// Global Variables for command line options. These should go into a -// structure at some point. -unsigned char debugmode = FALSE; - -// This function prints either to stdout or to the syslog as needed - -// [From GLIBC Manual: Since the prototype doesn't specify types for -// optional arguments, in a call to a variadic function the default -// argument promotions are performed on the optional argument -// values. This means the objects of type char or short int (whether -// signed or not) are promoted to either int or unsigned int, as -// appropriate.] -void printout(int priority,char *fmt, ...){ - va_list ap; - // initialize variable argument list - va_start(ap,fmt); - if (debugmode) - vprintf(fmt,ap); - else { - openlog("smartd",LOG_PID,LOG_DAEMON); - vsyslog(priority,fmt,ap); - closelog(); - } - va_end(ap); - return; -} - -// If either address or executable path is non-null then send and log -// a warning email, or execute executable -void printandmail(cfgfile *cfg, int which, int priority, char *fmt, ...){ - char command[2048], message[256], hostname[256], additional[256]; - char original[256], further[256], domainname[256], subject[256],dates[64]; - int status; - time_t epoch; - va_list ap; - const int day=24*3600; - int days=0; - char *whichfail[]={ - "emailtest", // 0 - "health", // 1 - "usage", // 2 - "selftest", // 3 - "errorcount" // 4 - "FAILEDhealthcheck", //5 - "FAILEDreadsmartdata", //6 - "FAILEDreadsmarterrorlog", //7 - "FAILEDreadsmartsefltestlog",//8 - "FAILEDopendevice" //9 - }; - - char *address=cfg->address; - char *executable=cfg->emailcmdline; - mailinfo *mail=cfg->maildata+which; - - // See if user wants us to send mail - if (!address && !executable) - return; - - // checks for sanity - if (cfg->emailfreq<1 || cfg->emailfreq>3) { - printout(LOG_INFO,"internal error in printandmail(): cfg->emailfreq=%d\n",cfg->emailfreq); - return; - } - if (which<0 || which>9) { - printout(LOG_INFO,"internal error in printandmail(): which=%d\n",which); - return; - } - - // Return if a single warning mail has been sent. - if ((cfg->emailfreq==1) && mail->logged) - return; - - // To decide if to send mail, we need to know what time it is. - epoch=time(NULL); - - // Return if less than one day has gone by - if (cfg->emailfreq==2 && mail->logged && epoch<(mail->lastsent+day)) - return; - - // Return if less than 2^(logged-1) days have gone by - if (cfg->emailfreq==3 && mail->logged){ - days=0x01<<(mail->logged-1); - days*=day; - if (epoch<(mail->lastsent+days)) - return; - } - - // record the time of this mail message, and the first mail message - if (!mail->logged) - mail->firstsent=epoch; - mail->lastsent=epoch; - - // get system host & domain names (not null terminated if length=MAX) - if (gethostname(hostname, 256)) - sprintf(hostname,"Unknown host"); - else - hostname[255]='\0'; - if (getdomainname(domainname, 256)) - sprintf(hostname,"Unknown domain"); - else - domainname[255]='\0'; - - // print warning string into message - va_start(ap, fmt); - vsnprintf(message, 256, fmt, ap); - va_end(ap); - - // appropriate message about further information - additional[0]=original[0]=further[0]='\0'; - if (which) { - sprintf(further,"You can also use the smartctl utility for further investigation.\n"); - - switch (cfg->emailfreq){ - case 1: - sprintf(additional,"No additional email messages about this problem will be sent.\n"); - break; - case 2: - sprintf(additional,"Another email message will be sent in 24 hours if the problem persists.\n"); - break; - case 3: - sprintf(additional,"Another email message will be sent in %d days if the problem persists\n", - (0x01)<<mail->logged); - break; - } - if (cfg->emailfreq>1 && mail->logged){ - dateandtimezoneepoch(dates, mail->firstsent); - sprintf(original,"The original email about this issue was sent at %s\n", dates); - } - } - - snprintf(subject, 256,"SMART error (%s) detected on host: %s", whichfail[which], hostname); - - // If the user has set cfg->emailcmdline, use that as mailer, else "mail". - if (!executable) - executable="mail"; - - // Export information in environment variables that will be useful - // for user scripts - setenv("SMARTD_MAILER", executable, 1); - setenv("SMARTD_DEVICE", cfg->name, 1); - setenv("SMARTD_DEVICETYPE", cfg->tryata?"ata":"scsi", 1); - setenv("SMARTD_MESSAGE", message, 1); - setenv("SMARTD_SUBJECT", subject, 1); - dateandtimezoneepoch(dates, mail->firstsent); - setenv("SMARTD_TFIRST", dates, 1); - snprintf(dates, 64,"%d", (int)mail->firstsent); - setenv("SMARTD_TFIRSTEPOCH", dates, 1); - setenv("SMARTD_FAILTYPE", whichfail[which], 1); - if (address) - setenv("SMARTD_ADDRESS", address, 1); - - // now construct a command to send this as EMAIL - if (address) - snprintf(command, 2048, - "$SMARTD_MAILER -s '%s' %s > /dev/null 2> /dev/null << \"ENDMAIL\"\n" - "This email was generated by the smartd daemon running on host:\n" - "%s\n" - "in the domain:\n" - "%s\n\n" - "The following warning/error was logged by the smartd daemon:\n" - "%s\n\n" - "For details see the SYSLOG (default: /var/log/messages) for host:\n" - "%s\n\n" - "%s%s%s" - "ENDMAIL\n", - subject, address, hostname, domainname, message, hostname, further, original, additional); - else - snprintf(command, 2048, "%s", executable); - - // tell SYSLOG what we are about to do... - printout(LOG_INFO,"%s %s to %s ...\n", - which?"Sending warning via ":"Executing test of", executable, address?address:"<nomailer>"); - - // issue the command to send mail or to run the user's executable - status=system(command); - - // now tell SYSLOG what happened. - if (status==-1){ - printout(LOG_CRIT,"%s %s to %s failed (unable to fork new process)\n", - which?"Warning via":"Test of", executable, address?address:"<nomailer>"); - } - else { - int status8; - // check and report exit status of command -#ifdef WEXITSTATUS - status8=WEXITSTATUS(status); -#else - status8=(status>>8) & 0xff; -#endif - if (status8) - printout(LOG_CRIT,"%s %s to %s failed (32-bit/8-bit exit status: %d/%d)\n", - which?"Warning via":"Test of", executable, address?address:"<nomailer>", status, status8); - else - printout(LOG_INFO,"%s %s to %s successful\n", - which?"Warning via":"Test of", executable, address?address:"<nomailer>"); - } - // increment mail sent counter - mail->logged++; - - return; -} - -// Printing function for watching ataprint commands, or losing them -void pout(char *fmt, ...){ - va_list ap; - // initialize variable argument list - va_start(ap,fmt); - // in debug==1 mode we will print the output from the ataprint.o functions! - if (debugmode && debugmode!=2) - vprintf(fmt,ap); - // in debug==2 mode we print output from knowndrives.o functions - else if (debugmode==2 || con->reportataioctl || con->reportscsiioctl) { - openlog("smartd", LOG_PID, LOG_DAEMON); - vsyslog(LOG_INFO, fmt, ap); - closelog(); - } - va_end(ap); - fflush(NULL); - return; -} - -// tell user that we ignore HUP signals -void huphandler(int sig){ - printout(LOG_CRIT,"HUP ignored: smartd does NOT re-read /etc/smartd.conf.\n"); - return; -} - -// signal handler that tells users about signals that were caught -void sighandler(int sig){ - printout(LOG_CRIT,"smartd received signal %d: %s\n", - sig, strsignal(sig)); - exit(EXIT_SIGNAL); -} - -// remove the PID file -void remove_pid_file(){ - if (pid_file) { - if ( -1==unlink(pid_file) ) - printout(LOG_INFO,"Can't unlink PID file %s (%s).\n", - pid_file, strerror(errno)); - free(pid_file); - } - return; -} - -// signal handler that prints goodbye message and removes pidfile -void goodbye(){ - printout(LOG_CRIT,"smartd is exiting\n"); - remove_pid_file(); - return; -} - -// Forks new process, closes all file descriptors, redirects stdin, -// stdout, stderr -void daemon_init(){ - pid_t pid; - int i; - - // flush all buffered streams. Else we might get two copies of open - // streams since both parent and child get copies of the buffers. - fflush(NULL); - - if ((pid=fork()) < 0) { - // unable to fork! - printout(LOG_CRIT,"smartd unable to fork daemon process!\n"); - exit(EXIT_STARTUP); - } - else if (pid) - // we are the parent process -- exit cleanly - exit(0); - - // from here on, we are the child process. - setsid(); - - // Fork one more time to avoid any possibility of having terminals - if ((pid=fork()) < 0) { - // unable to fork! - printout(LOG_CRIT,"smartd unable to fork daemon process!\n"); - exit(EXIT_STARTUP); - } - else if (pid) - // we are the parent process -- exit cleanly - exit(0); - - // Now we are the child's child... - - // close any open file descriptors - for (i=getdtablesize();i>=0;--i) - close(i); - - // redirect any IO attempts to /dev/null for stdin - i=open("/dev/null",O_RDWR); - // stdout - dup(i); - // stderr - dup(i); - umask(0); - chdir("/"); - - return; -} - -// create a PID file containing the current process id -void write_pid_file() { - if (pid_file) { - int error = 0; - pid_t pid = getpid(); - mode_t old_umask; - FILE* fp; - - old_umask = umask(0077); - fp = fopen(pid_file, "w"); - umask(old_umask); - if (fp == NULL) { - error = 1; - } else if (fprintf(fp, "%d\n", pid) <= 0) { - error = 1; - } else if (fclose(fp) != 0) { - error = 1; - } - if (error) { - printout(LOG_CRIT, "unable to write PID file %s - exiting.\n", pid_file); - exit(EXIT_PID); - } - printout(LOG_INFO, "file %s written containing PID %d\n", pid_file, pid); - } - return; -} - -// Prints header identifying version of code and home -void printhead(){ - printout(LOG_INFO,"smartd version %d.%d-%d Copyright (C) 2002-3 Bruce Allen\n", - (int)RELEASE_MAJOR, (int)RELEASE_MINOR, (int)SMARTMONTOOLS_VERSION); - printout(LOG_INFO,"Home page is %s\n\n",PROJECTHOME); - return; -} - - -// prints help info for configuration file Directives -void Directives() { - printout(LOG_INFO,"Configuration file (/etc/smartd.conf) Directives (after device name):\n"); - printout(LOG_INFO," -d TYPE Set the device type to one of: ata, scsi\n"); - printout(LOG_INFO," -T TYPE set the tolerance to one of: normal, permissive\n"); - printout(LOG_INFO," -o VAL Enable/disable automatic offline tests (on/off)\n"); - printout(LOG_INFO," -S VAL Enable/disable attribute autosave (on/off)\n"); - printout(LOG_INFO," -H Monitor SMART Health Status, report if failed\n"); - printout(LOG_INFO," -l TYPE Monitor SMART log. Type is one of: error, selftest\n"); - printout(LOG_INFO," -f Monitor 'Usage' Attributes, report failures\n"); - printout(LOG_INFO," -m ADD Send email warning to address ADD\n"); - printout(LOG_INFO," -M TYPE Modify email warning behavior (see man page)\n"); - printout(LOG_INFO," -p Report changes in 'Prefailure' Attributes\n"); - printout(LOG_INFO," -u Report changes in 'Usage' Attributes\n"); - printout(LOG_INFO," -t Equivalent to -p and -u Directives\n"); - printout(LOG_INFO," -r ID Also report Raw values of Attribute ID with -p, -u or -t\n"); - printout(LOG_INFO," -R ID Track changes in Attribute ID Raw value with -p, -u or -t\n"); - printout(LOG_INFO," -i ID Ignore Attribute ID for -f Directive\n"); - printout(LOG_INFO," -I ID Ignore Attribute ID for -p, -u or -t Directive\n"); - printout(LOG_INFO," -v N,ST Modifies labeling of Attribute N (see man page) \n"); - printout(LOG_INFO," -P TYPE Drive-specific presets: use, ignore, show, showall\n"); - printout(LOG_INFO," -a Default: equivalent to -H -f -t -l error -l selftest\n"); - printout(LOG_INFO," -F TYPE Use firmware bug workaround. Type is one of: none, samsung\n"); - printout(LOG_INFO," # Comment: text after a hash sign is ignored\n"); - printout(LOG_INFO," \\ Line continuation character\n"); - printout(LOG_INFO,"Attribute ID is a decimal integer 1 <= ID <= 255\n"); - printout(LOG_INFO,"SCSI devices: only -d, -m, and -M Directives allowed.\n"); - printout(LOG_INFO,"Example: /dev/hda -a\n"); -return; -} - -/* prints help information for command syntax */ -void Usage (void){ - printout(LOG_INFO,"Usage: smartd [options]\n\n"); -#ifdef HAVE_GETOPT_LONG - printout(LOG_INFO," -c, --checkonce\n"); - printout(LOG_INFO," Check all devices once, then exit\n\n"); - printout(LOG_INFO," -d, --debug\n"); - printout(LOG_INFO," Start smartd in debug mode\n\n"); - printout(LOG_INFO," -D, --showdirectives\n"); - printout(LOG_INFO," Print the configuration file Directives and exit\n\n"); - printout(LOG_INFO," -h, -?, --help, --usage\n"); - printout(LOG_INFO," Display this help and exit\n\n"); - printout(LOG_INFO," -i N, --interval=N\n"); - printout(LOG_INFO," Set interval between disk checks to N seconds, where N >= 10\n\n"); - printout(LOG_INFO," -p NAME, --pidfile=NAME\n"); - printout(LOG_INFO," Write PID file NAME\n\n"); - printout(LOG_INFO," -r, --report=TYPE\n"); - printout(LOG_INFO," Report transactions for one of: %s\n\n", getvalidarglist('r')); - printout(LOG_INFO," -V, --version, --license, --copyright\n"); - printout(LOG_INFO," Print License, Copyright, and version information\n"); -#else - printout(LOG_INFO," -c Check all devices once, then exit\n"); - printout(LOG_INFO," -d Start smartd in debug mode\n"); - printout(LOG_INFO," -D Print the configuration file Directives and exit\n"); - printout(LOG_INFO," -h Display this help and exit\n"); - printout(LOG_INFO," -i N Set interval between disk checks to N seconds, where N >= 10\n"); - printout(LOG_INFO," -p NAME Write PID file NAME\n"); - printout(LOG_INFO," -r TYPE Report transactions for one of: %s\n", getvalidarglist('r')); - printout(LOG_INFO," -V Print License, Copyright, and version information\n"); - printout(LOG_INFO," -? Same as -h\n"); -#endif -} - -// returns negative if problem, else fd>=0 -static int opendevice(char *device, int flags) -{ - int fd; - - fd = open(device, flags); - if (fd < 0) { - printout(LOG_INFO,"Device: %s, %s, open() failed\n", - device, strerror(errno)); - return -1; - } - // device opened sucessfully - return fd; -} - -int closedevice(int fd, char *name){ - if (close(fd)){ - printout(LOG_INFO,"Device: %s, %s, close(%d) failed\n", name, strerror(errno), fd); - return 1; - } - // device sucessfully closed - return 0; -} - -// returns <0 on failure -int ataerrorcount(int fd, char *name){ - struct ata_smart_errorlog log; - - if (-1==ataReadErrorLog(fd,&log)){ - printout(LOG_INFO,"Device: %s, Read SMART Error Log Failed\n",name); - return -1; - } - - // return current number of ATA errors - return log.error_log_pointer?log.ata_error_count:0; -} - -// returns <0 if problem -int selftesterrorcount(int fd, char *name){ - struct ata_smart_selftestlog log; - - if (-1==ataReadSelfTestLog(fd,&log)){ - printout(LOG_INFO,"Device: %s, Read SMART Self Test Log Failed\n",name); - return -1; - } - - // return current number of self-test errors - return ataPrintSmartSelfTestlog(&log,0); -} - - - -// scan to see what ata devices there are, and if they support SMART -int atadevicescan2(atadevices_t *devices, cfgfile *cfg){ - int fd; - struct hd_driveid drive; - char *device=cfg->name; - - // should we try to register this as an ATA device? - if (!(cfg->tryata)) - return 1; - - // open the device - if ((fd=opendevice(device, O_RDONLY | O_NONBLOCK))<0) - // device open failed - return 1; - printout(LOG_INFO,"Device: %s, opened\n", device); - - // Get drive identity structure - if (ataReadHDIdentity (fd,&drive)){ - // Unable to read Identity structure - printout(LOG_INFO,"Device: %s, unable to read Device Identity Structure\n",device); - close(fd); - return 2; - } - - // pass user setings on to low-level ATA commands - con->fixfirmwarebug = cfg->fixfirmwarebug; - - // Show if device in database, and use preset vendor attribute - // options unless user has requested otherwise. - if (!cfg->ignorepresets){ - - // do whatever applypresets decides to do - if (applypresets(&drive, cfg->attributedefs, con)<0) - printout(LOG_INFO, "Device: %s, not found in smartd database.\n", device); - else - printout(LOG_INFO, "Device: %s, found in smartd database.\n", device); - - // then save the correct state of the flag (applypresets may have changed it) - cfg->fixfirmwarebug = con->fixfirmwarebug; - } - else - printout(LOG_INFO, "Device: %s, smartd database not searched (Directive: -P ignore).\n", device); - - // If requested, show which presets would be used for this drive - if (cfg->showpresets) { - int savedebugmode=debugmode; - printout(LOG_INFO, "Device %s: presets are:\n", device); - if (!debugmode) - debugmode=2; - showpresets(&drive); - debugmode=savedebugmode; - } - - if (!cfg->permissive && !ataSmartSupport(&drive)){ - // SMART not supported - printout(LOG_INFO,"Device: %s, appears to lack SMART, use '-T permissive' Directive to try anyway.\n",device); - close(fd); - return 2; - } - - if (ataEnableSmart(fd)){ - // Enable SMART command has failed - printout(LOG_INFO,"Device: %s, could not enable SMART capability\n",device); - close(fd); - return 2; - } - - // disable device attribute autosave... - if (cfg->autosave==1){ - if (ataDisableAutoSave(fd)) - printout(LOG_INFO,"Device: %s, could not disable SMART Attribute Autosave.\n",device); - else - printout(LOG_INFO,"Device: %s, disabled SMART Attribute Autosave.\n",device); - } - - // or enable device attribute autosave - if (cfg->autosave==2){ - if (ataEnableAutoSave(fd)) - printout(LOG_INFO,"Device: %s, could not enable SMART Attribute Autosave.\n",device); - else - printout(LOG_INFO,"Device: %s, enabled SMART Attribute Autosave.\n",device); - } - - // capability check: SMART status - if (cfg->smartcheck && ataSmartStatus2(fd)==-1){ - printout(LOG_INFO,"Device: %s, not capable of SMART Health Status check\n",device); - cfg->smartcheck=0; - } - - // capability check: Read smart values and thresholds - if (cfg->usagefailed || cfg->prefail || cfg->usage || cfg->autoofflinetest) { - devices->smartval=(struct ata_smart_values *)calloc(1,sizeof(struct ata_smart_values)); - devices->smartthres=(struct ata_smart_thresholds *)calloc(1,sizeof(struct ata_smart_thresholds)); - - if (!devices->smartval || !devices->smartthres){ - printout(LOG_CRIT,"Not enough memory to obtain SMART data\n"); - exit(EXIT_NOMEM); - } - - if (ataReadSmartValues(fd,devices->smartval) || - ataReadSmartThresholds (fd,devices->smartthres)){ - printout(LOG_INFO,"Device: %s, Read SMART Values and/or Thresholds Failed\n",device); - free(devices->smartval); - free(devices->smartthres); - - // make it easy to recognize that we've deallocated - devices->smartval=NULL; - devices->smartthres=NULL; - cfg->usagefailed=cfg->prefail=cfg->usage=0; - } - } - - // disable automatic on-line testing - if (cfg->autoofflinetest==1){ - if (devices->smartval && isSupportAutomaticTimer(devices->smartval) && !ataDisableAutoOffline(fd)) - printout(LOG_INFO,"Device: %s, disabled SMART Automatic Offline Testing .\n",device); - else - printout(LOG_INFO,"Device: %s, could not disable SMART Automatic Offline Testing.\n",device); - } - - // enable automatic on-line testing - if (cfg->autoofflinetest==2){ - if (devices->smartval && isSupportAutomaticTimer(devices->smartval) && !ataDisableAutoOffline(fd)) - printout(LOG_INFO,"Device: %s, enabled SMART Automatic Offline Testing.\n",device); - else - printout(LOG_INFO,"Device: %s, could not enable SMART Automatic Offline Testing.\n",device); - } - - // capability check: self-test-log - if (cfg->selftest){ - int val; - - // see if device supports Self-test logging. Note that the - // following line is not a typo: Device supports self-test log if - // and only if it also supports error log. - if (!isSmartErrorLogCapable(devices->smartval)){ - printout(LOG_INFO, "Device: %s, does not support SMART Self-test Log.\n", device); - cfg->selftest=0; - cfg->selflogcount=0; - } - else { - // get number of Self-test errors logged - val=selftesterrorcount(fd, device); - if (val>=0) - cfg->selflogcount=val; - else - cfg->selftest=0; - } - } - - // capability check: ATA error log - if (cfg->errorlog){ - int val; - - // see if device supports error logging - if (!isSmartErrorLogCapable(devices->smartval)){ - printout(LOG_INFO, "Device: %s, does not support SMART Error Log.\n", device); - cfg->errorlog=0; - cfg->ataerrorcount=0; - } - else { - // get number of ATA errors logged - val=ataerrorcount(fd, device); - if (val>=0) - cfg->ataerrorcount=val; - else - cfg->errorlog=0; - } - } - - // If no tests available or selected, return - if (!(cfg->errorlog || cfg->selftest || cfg->smartcheck || - cfg->usagefailed || cfg->prefail || cfg->usage)) { - close(fd); - return 3; - } - - // Do we still have entries available? - if (numatadevices>=MAXATADEVICES){ - printout(LOG_CRIT,"smartd has found more than MAXATADEVICES=%d ATA devices.\n" - "Recompile code from " PROJECTHOME " with larger MAXATADEVICES\n",(int)numatadevices); - exit(EXIT_CCONST); - } - - // register device - printout(LOG_INFO,"Device: %s, is SMART capable. Adding to \"monitor\" list.\n",device); - - // we were called from a routine that has global storage for the name. Keep pointer. - devices->devicename=device; - devices->cfg=cfg; - - // record number of device, type of device, increment device count - cfg->tryscsi=0; - cfg->tryata=1; - cfg->atadevicenum=numatadevices; - cfg->scsidevicenum=-1; - numatadevices++; - - // close file descriptor - closedevice(fd, device); - return 0; -} - - -static int scsidevicescan(scsidevices_t *devices, cfgfile *cfg, - int scandirective) -{ - int k, fd, err; - char *device = cfg->name; - struct scsi_iec_mode_page iec; - UINT8 tBuf[64]; - - // should we try to register this as a SCSI device? - if (! cfg->tryscsi) - return 1; - // open the device - if ((fd = opendevice(device, O_RDWR | O_NONBLOCK)) < 0) { - if (scandirective) - return 1; - printout(LOG_WARNING, "Device: %s, skip\n", device); - return 0; // device open failed - } - printout(LOG_INFO,"Device: %s, opened\n", device); - - // check that it's ready for commands. IE stores its stuff on the media. - if ((err = scsiTestUnitReady(fd))) { - if (1 == err) { - printout(LOG_WARNING, "Device: %s, NOT READY (media absent, spun " - "down); skip\n", device); - close(fd); - return scandirective ? 1 : 0; - } else { - printout(LOG_ERR, "Device: %s, failed Test Unit Ready [err=%d]\n", - device, err); - close(fd); - return 2; - } - } - - if ((err = scsiFetchIECmpage(fd, &iec))) { - printout(LOG_WARNING, "Device: %s, Fetch of IEC (SMART) mode page " - "failed, err=%d, skip device\n", device, err); - return 0; - } - if (! scsi_IsExceptionControlEnabled(&iec)) { - printout(LOG_WARNING, "Device: %s, IE (SMART) not enabled, " - "skip device\n", device); - close(fd); - return 0; - } - - // Device exists, and does SMART. Add to list - if (numscsidevices >= MAXSCSIDEVICES) { - printout(LOG_ERR, "smartd has found more than MAXSCSIDEVICES=%d " - "SCSI devices.\n" "Recompile code from " PROJECTHOME - " with larger MAXSCSIDEVICES\n", (int)numscsidevices); - return 0; - } - - // now we can proceed to register the device - printout(LOG_INFO, "Device: %s, is SMART capable. Adding " - "to \"monitor\" list.\n",device); - - // since device points to global memory, just keep that address - devices->devicename = device; - devices->cfg = cfg; - - // Flag that certain log pages are supported (information may be - // available from other sources). - if (0 == scsiLogSense(fd, SUPPORTED_LOG_PAGES, tBuf, sizeof(tBuf))) { - for (k = 4; k < tBuf[3] + LOGPAGEHDRSIZE; ++k) { - switch (tBuf[k]) { - case TEMPERATURE_PAGE: - devices->TempPageSupported = 1; - break; - case IE_LOG_PAGE: - devices->SmartPageSupported = 1; - break; - default: - break; - } - } - } - - // record number of device, type of device, increment device count - cfg->tryata = 0; - cfg->tryscsi = 1; - cfg->scsidevicenum = numscsidevices; - cfg->atadevicenum = -1; - ++numscsidevices; - - // close file descriptor - closedevice(fd, device); - return 0; -} - -// 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. -int ataCompareSmartValues(changedattribute_t *delta, - struct ata_smart_values *new, - struct ata_smart_values *old, - struct ata_smart_thresholds *thresholds, - int n, 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 || !new || !old || !thresholds) - return 0; - - // pointers to disk's values and vendor's thresholds - now=new->vendor_attributes+n; - was=old->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=now->status.flag.prefailure; - delta->sameraw=sameraw; - - return 1; -} - -// This looks to see if the corresponding bit of the 32 bytes is set. -// This wastes a few bytes of storage but eliminates all searching and -// sorting functions! Entry is ZERO <==> the attribute ON. Calling -// with set=0 tells you if the attribute is being tracked or not. -// Calling with set=1 turns the attribute OFF. -int isattoff(unsigned char attr,unsigned char *data, int set){ - // locate correct attribute - int loc=attr>>3; - int bit=attr & 0x07; - unsigned char mask=0x01<<bit; - - // attribute zero is always OFF - if (!attr) - return 1; - - if (!set) - return (data[loc] & mask); - - data[loc]|=mask; - // return value when setting makes no sense! - return 0; -} - - -int ataCheckDevice(atadevices_t *drive){ - int fd,i; - char *name=drive->devicename; - cfgfile *cfg=drive->cfg; - - // fix firmware bug if requested - con->fixfirmwarebug=cfg->fixfirmwarebug; - - // If user has asked, test the email warning system - if (cfg->emailtest){ - printandmail(cfg, 0, LOG_CRIT, "TEST EMAIL from smartd for device: %s", drive->devicename); - } - - // if we can't open device, fail gracefully rather than hard -- - // perhaps the next time around we'll be able to open it. ATAPI - // cd/dvd devices will hang awaiting media if O_NONBLOCK is not - // given (see linux cdrom driver). - if ((fd=opendevice(name, O_RDONLY | O_NONBLOCK))<0){ - printandmail(cfg, 9, LOG_CRIT, "Device: %s, unable to open device", name); - return 1; - } - - // check smart status - if (cfg->smartcheck){ - int status=ataSmartStatus2(fd); - if (status==-1){ - printout(LOG_INFO,"Device: %s, not capable of SMART self-check\n",name); - printandmail(cfg, 5, LOG_CRIT, "Device: %s, not capable of SMART self-check", name); - } - else if (status==1){ - printout(LOG_CRIT, "Device: %s, FAILED SMART self-check. BACK UP DATA NOW!\n", name); - printandmail(cfg, 1, LOG_CRIT, "Device: %s, FAILED SMART self-check. BACK UP DATA NOW!", name); - } - } - - // Check everything that depends upon SMART Data (eg, Attribute values) - if (cfg->usagefailed || cfg->prefail || cfg->usage){ - struct ata_smart_values curval; - struct ata_smart_thresholds *thresh=drive->smartthres; - - // Read current attribute values. *drive contains old values and thresholds - if (ataReadSmartValues(fd,&curval)){ - printout(LOG_CRIT, "Device: %s, failed to read SMART Attribute Data\n", name); - printandmail(cfg, 6, LOG_CRIT, "Device: %s, failed to read SMART Attribute Data", name); - } - else { - // look for failed usage attributes, or track usage or prefail attributes - for (i=0; i<NUMBER_ATA_SMART_ATTRIBUTES; i++){ - int att; - changedattribute_t delta; - - - // 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. - if (cfg->usagefailed && ((att=ataCheckAttribute(&curval, thresh, i))<0)){ - - // are we ignoring failures of this attribute? - att *= -1; - if (!isattoff(att, cfg->monitorattflags, 0)){ - char attname[64], *loc=attname; - - // get attribute name & skip white space - ataPrintSmartAttribName(loc, att, cfg->attributedefs[att]); - while (*loc && *loc==' ') loc++; - - // warning message - printout(LOG_CRIT, "Device: %s, Failed SMART usage Attribute: %s.\n", name, loc); - printandmail(cfg, 2, LOG_CRIT, "Device: %s, Failed SMART usage Attribute: %s.", name, loc); - } - } - - // 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. - if ((cfg->usage || cfg->prefail) && ataCompareSmartValues(&delta, &curval, drive->smartval, thresh, i, name)){ - unsigned char id=delta.id; - - // 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 && !isattoff(id, cfg->monitorattflags+96, 0)) - continue; - - // are we tracking this attribute? - if (!isattoff(id, cfg->monitorattflags+32, 0)){ - char newrawstring[64], oldrawstring[64], attname[64], *loc=attname; - - // get attribute name, skip spaces - ataPrintSmartAttribName(loc, id, cfg->attributedefs[id]); - while (*loc && *loc==' ') loc++; - - // has the user asked for us to print raw values? - if (isattoff(id, cfg->monitorattflags+64, 0)) { - // 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, drive->smartval->vendor_attributes+i, cfg->attributedefs); - sprintf(oldrawstring, " [Raw %s]", rawstring); - } - else - newrawstring[0]=oldrawstring[0]='\0'; - - // prefailure attribute - if (cfg->prefail && delta.prefail) - printout(LOG_INFO, "Device: %s, SMART Prefailure Attribute: %s changed from %d%s to %d%s\n", - name, loc, delta.oldval, oldrawstring, delta.newval, newrawstring); - - // usage attribute - if (cfg->usage && !delta.prefail) - printout(LOG_INFO, "Device: %s, SMART Usage Attribute: %s changed from %d%s to %d%s\n", - name, loc, delta.oldval, oldrawstring, delta.newval, newrawstring); - } - } // endof block tracking usage or prefailure - } // end of loop over attributes - - // Save the new values into *drive for the next time around - *drive->smartval=curval; - } - } - - // check if number of selftest errors has increased (note: may also DECREASE) - if (cfg->selftest){ - int new; - unsigned char old=cfg->selflogcount; - - // new self test error count - new=selftesterrorcount(fd, name); - - // did command fail? - if (new<0) - printandmail(cfg, 8, LOG_CRIT, "Device: %s, Read SMART Self Test Log Failed", name); - - // hsa self-test error count increased? - if (new>old){ - printout(LOG_CRIT, "Device: %s, Self-Test Log error count increased from %d to %d\n", - name, (int)old, new); - printandmail(cfg, 3, LOG_CRIT, "Device: %s, Self-Test Log error count increased from %d to %d", - name, (int)old, new); - } - - // Needed since self-test error count may DECREASE - if (new>=0) - cfg->selflogcount=new; - } - - - // check if number of ATA errors has increased - if (cfg->errorlog){ - - int new,old=cfg->ataerrorcount; - - // new number of errors - new=ataerrorcount(fd, name); - - // did command fail? - if (new<0) - printandmail(cfg, 7, LOG_CRIT, "Device: %s, Read SMART Error Log Failed", name); - - // has error count increased? - if (new>old){ - printout(LOG_CRIT, "Device: %s, ATA error count increased from %d to %d\n", - name, old, new); - printandmail(cfg, 4, LOG_CRIT, "Device: %s, ATA error count increased from %d to %d", - name, old, new); - } - - // this last line is probably not needed, count always increases - if (new>=0) - cfg->ataerrorcount=new; - } - - // Don't leave device open -- the OS/user may want to access it - // before the next smartd cycle! - closedevice(fd, name); - return 0; -} - - -int scsiCheckDevice(scsidevices_t *drive) -{ - UINT8 asc, ascq; - UINT8 currenttemp; - int fd; - cfgfile *cfg=drive->cfg; - char *name=drive->devicename; - const char *cp; - - // If the user has asked for it, test the email warning system - if (cfg->emailtest) - printandmail(cfg, 0, LOG_CRIT, - "TEST EMAIL from smartd for device: %s", name); - - // if we can't open device, fail gracefully rather than hard -- - // perhaps the next time around we'll be able to open it - if ((fd=opendevice(name, O_RDWR | O_NONBLOCK))<0) { - printandmail(cfg, 9, LOG_CRIT, "Device: %s, unable to open device", - name); - return 1; - } - currenttemp = 0; - asc = 0; - ascq = 0; - if (scsiCheckIE(fd, drive->SmartPageSupported, drive->TempPageSupported, - &asc, &ascq, ¤ttemp)) { - printout(LOG_INFO, "Device: %s, failed to read SMART values\n", name); - printandmail(cfg, 6, LOG_CRIT, - "Device: %s, failed to read SMART values", name); - } - if (asc > 0) { - cp = scsiGetIEString(asc, ascq); - if (cp) { - printout(LOG_CRIT, "Device: %s, SMART Failure: %s\n", name, cp); - printandmail(cfg, 1, LOG_CRIT, "Device: %s, SMART Failure: %s", - name, cp); - } - } else if (debugmode) - printout(LOG_INFO,"Device: %s, Acceptable asc,ascq: %d,%d\n", - name, (int)asc, (int)ascq); - - // Seems to completely ignore what capabilities were found on the - // device when scanned - if (currenttemp) { - if (255 == currenttemp) /* this means temperature unavailable */ - currenttemp = 0; /* less likely to worry people */ - if ((currenttemp != drive->Temperature) && (drive->Temperature)) - printout(LOG_INFO, "Device: %s, Temperature changed %d degrees " - "to %d degrees since last reading\n", name, - (int)(currenttemp - drive->Temperature), - (int)currenttemp); - drive->Temperature = currenttemp; - } - closedevice(fd, name); - return 0; -} - -void CheckDevices(atadevices_t *atadevices, scsidevices_t *scsidevices){ - static int firstpass=1; - int i; - - // Infinite loop, which checks devices - printout(LOG_INFO,"Started monitoring %d ATA and %d SCSI devices\n",numatadevices,numscsidevices); - while (1){ - for (i=0; i<numatadevices; i++) - ataCheckDevice(atadevices+i); - - for (i=0; i<numscsidevices; i++) - scsiCheckDevice(scsidevices+i); - - // This option is primarily for distribution developers who want - // an automated procedure for seeing if smartd works correctly. - // Use the -c/--checkonce option and verify zero exit status. - if (checkonce) { - printout(LOG_INFO,"Started with '-c' option. All devices sucessfully checked once.\n"); - exit(0); - } - - // Initialization setup - if (firstpass){ - - // If in background as a daemon, fork and close file descriptors - if (!debugmode) - daemon_init(); - - // install goobye message and remove pidfile handler - atexit(goodbye); - - // write PID file only after installing exit handler - if (!debugmode) - write_pid_file(); - - // install signal handlers - if (signal(SIGINT, sighandler)==SIG_IGN) - signal(SIGINT, SIG_IGN); - if (signal(SIGTERM, sighandler)==SIG_IGN) - signal(SIGTERM, SIG_IGN); - if (signal(SIGQUIT, sighandler)==SIG_IGN) - signal(SIGQUIT, SIG_IGN); - if (signal(SIGHUP, huphandler)==SIG_IGN) - signal(SIGHUP, SIG_IGN); - if (signal(SIGUSR1, sleephandler)==SIG_IGN) - signal(SIGUSR1, SIG_IGN); - - // done with initialization setup - firstpass=0; - } - - // Unix Gurus: I know that this can be done better. Please tell - // me how -- use email address for Bruce Allen at the top of this - // file. Search for "sleeptime" to see what I am doing. I think - // that when done "right" I should not have to call sleep once per - // second, but just set an alarm for checktime in the future, and - // then have an additional alarm sent if the user does SIGUSR1, - // which arrives first to cause another device check. Please help - // me out. - - // Sleep until next check. Note that since sleeptime can be set to - // zero by an EXTERNAL signal SIGUSR1, it's possible for sleeptime - // to be negative. Don't use while (sleeptime)! - sleeptime=checktime; - while (sleeptime-->0) - sleep(1); - } -} - -// Print out a list of valid arguments for the Directive d -void printoutvaliddirectiveargs(int priority, char d) { - char *s; - - switch (d) { - case 'd': - printout(priority, "ata, scsi"); - break; - case 'T': - printout(priority, "normal, permissive"); - break; - case 'o': - case 'S': - printout(priority, "on, off"); - break; - case 'l': - printout(priority, "error, selftest"); - break; - case 'M': - printout(priority, "\"once\", \"daily\", \"diminishing\", \"test\", \"exec\""); - break; - case 'v': - if (!(s = create_vendor_attribute_arg_list())) { - printout(LOG_CRIT,"Insufficient memory to construct argument list\n"); - break; - } - printout(priority, "\n%s\n", s); - free(s); - break; - case 'P': - printout(priority, "use, ignore, show, showall"); - break; - case 'F': - printout(priority, "none, samsung"); - break; - } -} - -char copyleftstring[]= -"smartd comes with ABSOLUTELY NO WARRANTY. This\n" -"is free software, and you are welcome to redistribute it\n" -"under the terms of the GNU General Public License Version 2.\n" -"See http://www.gnu.org for further details.\n\n"; - -cfgfile config[MAXENTRIES]; - -// exits with an error message, or returns integer value of token -int inttoken(char *arg, char *name, char *token, int lineno, char *configfile, int min, int max){ - char *endptr; - int val; - - // make sure argument is there - if (!arg) { - printout(LOG_CRIT,"File %s line %d (drive %s): Directive: %s takes integer argument from %d to %d.\n", - configfile, lineno, name, token, min, max); - Directives(); - exit(EXIT_BADCONF); - } - - // get argument value (base 10), check that it's integer, and in-range - val=strtol(arg,&endptr,10); - if (*endptr!='\0' || val<min || val>max ) { - printout(LOG_CRIT,"File %s line %d (drive %s): Directive: %s has argument: %s; needs integer from %d to %d.\n", - configfile, lineno, name, token, arg, min, max); - Directives(); - exit(EXIT_BADCONF); - } - - // all is well; return value - return val; -} - -// This function returns non-zero if it has correctly parsed a token, -// else zero if it has failed to parse a token. Or it exits with a -// Directive message if there is a token-parsing problem. -int parsetoken(char *token,cfgfile *cfg){ - char sym; - char *name=cfg->name; - int lineno=cfg->lineno; - char *delim = " \n\t"; - int badarg = 0; - int missingarg = 0; - char *arg = NULL; - - // is the rest of the line a comment - if (*token=='#') - return 1; - - // is the token not recognized? - if (*token!='-' || strlen(token)!=2) { - printout(LOG_CRIT,"File %s line %d (drive %s): unknown Directive: %s\n", - CONFIGFILE, lineno, name, token); - Directives(); - exit(EXIT_BADCONF); - } - - // let's parse the token and swallow its argument - switch (sym=token[1]) { - int val; - - case 'T': - // Set tolerance level for SMART command failures - if ((arg = strtok(NULL, delim)) == NULL) { - missingarg = 1; - } else if (!strcmp(arg, "normal")) { - // Normal mode: exit on failure of a mandatory S.M.A.R.T. command, but - // not on failure of an optional S.M.A.R.T. command. - // This is the default so we don't need to actually do anything here. - ; - } else if (!strcmp(arg, "permissive")) { - // Permissive mode; ignore errors from Mandatory SMART commands - cfg->permissive = 1; - } else { - badarg = 1; - } - break; - case 'd': - // specify the device type - if ((arg = strtok(NULL, delim)) == NULL) { - missingarg = 1; - } else if (!strcmp(arg, "ata")) { - cfg->tryata = 1; - cfg->tryscsi = 0; - } else if (!strcmp(arg, "scsi")) { - cfg->tryscsi = 1; - cfg->tryata = 0; - } else { - badarg = 1; - } - break; - case 'F': - // fix firmware bug - if ((arg = strtok(NULL, delim)) == NULL) { - missingarg = 1; - } else if (!strcmp(arg, "none")) { - cfg->fixfirmwarebug = FIX_NONE; - } else if (!strcmp(arg, "samsung")) { - cfg->fixfirmwarebug = FIX_SAMSUNG; - } else { - badarg = 1; - } - break; - case 'H': - // check SMART status - cfg->smartcheck=1; - break; - case 'f': - // check for failure of usage attributes - cfg->usagefailed=1; - break; - case 't': - // track changes in all vendor attributes - cfg->prefail=1; - cfg->usage=1; - break; - case 'p': - // track changes in prefail vendor attributes - cfg->prefail=1; - break; - case 'u': - // track changes in usage vendor attributes - cfg->usage=1; - break; - case 'l': - // track changes in SMART logs - if ((arg = strtok(NULL, delim)) == NULL) { - missingarg = 1; - } else if (!strcmp(arg, "selftest")) { - // track changes in self-test log - cfg->selftest=1; - } else if (!strcmp(arg, "error")) { - // track changes in ATA error log - cfg->errorlog=1; - } else { - badarg = 1; - } - break; - case 'a': - // monitor everything - cfg->smartcheck=1; - cfg->prefail=1; - cfg->usagefailed=1; - cfg->usage=1; - cfg->selftest=1; - cfg->errorlog=1; - break; - case 'o': - if ((arg = strtok(NULL, delim)) == NULL) { - missingarg = 1; - } else if (!strcmp(arg, "on")) { - cfg->autoofflinetest = 2; - } else if (!strcmp(arg, "off")) { - cfg->autoofflinetest = 1; - } else { - badarg = 1; - } - break; - case 'S': - if ((arg = strtok(NULL, delim)) == NULL) { - missingarg = 1; - } else if (!strcmp(arg, "on")) { - cfg->autosave = 2; - } else if (!strcmp(arg, "off")) { - cfg->autosave = 1; - } else { - badarg = 1; - } - break; - case 'M': - // email warning option - if ((arg = strtok(NULL, delim)) == NULL) { - missingarg = 1; - } else if (!strcmp(arg, "once")) { - cfg->emailfreq = 1; - } else if (!strcmp(arg, "daily")) { - cfg->emailfreq = 2; - } else if (!strcmp(arg, "diminishing")) { - cfg->emailfreq = 3; - } else if (!strcmp(arg, "test")) { - cfg->emailtest = 1; - } else if (!strcmp(arg, "exec")) { - // Get the next argument (the command line) - if ((arg = strtok(NULL, delim)) == NULL) { - printout(LOG_CRIT, "File %s line %d (drive %s): Directive %s 'exec' argument must be followed by executable path.\n", - CONFIGFILE, lineno, name, token); - Directives(); - exit(EXIT_BADCONF); - } - // Free the last cmd line given if any - if (cfg->emailcmdline) { - printout(LOG_INFO, "File %s line %d (drive %s): found multiple -M exec Directives on line - ignoring all but the last\n", CONFIGFILE, lineno, name); - free(cfg->emailcmdline); - } - // Attempt to copy the argument - if (!(cfg->emailcmdline = strdup(arg))) { - printout(LOG_CRIT, "File %s line %d (drive %s): no free memory for command line argument to exec: %s\n", - CONFIGFILE, lineno, name, arg); - Directives(); - exit(EXIT_NOMEM); - } - } else { - badarg = 1; - } - break; - case 'i': - // ignore failure of usage attribute - val=inttoken(arg=strtok(NULL,delim), name, token, lineno, CONFIGFILE, 1, 255); - isattoff(val,cfg->monitorattflags,1); - break; - case 'I': - // ignore attribute for tracking purposes - val=inttoken(arg=strtok(NULL,delim), name, token, lineno, CONFIGFILE, 1, 255); - isattoff(val,cfg->monitorattflags+32,1); - break; - case 'r': - // print raw value when tracking - val=inttoken(arg=strtok(NULL,delim), name, token, lineno, CONFIGFILE, 1, 255); - isattoff(val,cfg->monitorattflags+64,1); - break; - case 'R': - // track changes in raw value (forces printing of raw value) - val=inttoken(arg=strtok(NULL,delim), name, token, lineno, CONFIGFILE, 1, 255); - isattoff(val,cfg->monitorattflags+64,1); - isattoff(val,cfg->monitorattflags+96,1); - break; - case 'm': - // send email to address that follows - if ((arg = strtok(NULL,delim)) == NULL) { - printout(LOG_CRIT,"File %s line %d (drive %s): Directive: %s needs email address(es)\n", - CONFIGFILE, lineno, name, token); - Directives(); - exit(EXIT_BADCONF); - } - if (!(cfg->address=strdup(arg))){ - printout(LOG_CRIT,"File %s line %d (drive %s): Directive: %s: no free memory for email address(es) %s\n", - CONFIGFILE, lineno, name, token, arg); - Directives(); - exit(EXIT_NOMEM); - } - break; - case 'v': - // non-default vendor-specific attribute meaning - if ((arg=strtok(NULL,delim)) == NULL) { - missingarg = 1; - } else if (parse_attribute_def(arg, cfg->attributedefs)){ - badarg = 1; - } - break; - case 'P': - // Define use of drive-specific presets. - if ((arg = strtok(NULL, delim)) == NULL) { - missingarg = 1; - } else if (!strcmp(arg, "use")) { - cfg->ignorepresets = FALSE; - } else if (!strcmp(arg, "ignore")) { - cfg->ignorepresets = TRUE; - } else if (!strcmp(arg, "show")) { - cfg->showpresets = TRUE; - } else if (!strcmp(arg, "showall")) { - debugmode = TRUE; - showallpresets(); - exit(0); - } else { - badarg = 1; - } - break; - default: - // Directive not recognized - printout(LOG_CRIT,"File %s line %d (drive %s): unknown Directive: %s\n", - CONFIGFILE, lineno, name, token); - Directives(); - exit(EXIT_BADCONF); - } - if (missingarg) { - printout(LOG_CRIT, "File %s line %d (drive %s): Missing argument to Directive: %s\n", CONFIGFILE, lineno, name, token); - } - if (badarg) { - printout(LOG_CRIT, "File %s line %d (drive %s): Invalid argument: %s\n", CONFIGFILE, lineno, name, arg); - } - if (missingarg || badarg) { - printout(LOG_CRIT, "Valid arguments to %s Directive are: ", token); - printoutvaliddirectiveargs(LOG_CRIT, sym); - printout(LOG_CRIT, "\n"); - Directives(); - exit(EXIT_BADCONF); - } - return 1; -} - -int parseconfigline(int entry, int lineno,char *line){ - char *token,*copy; - char *name; - char *delim = " \n\t"; - cfgfile *cfg; - static int numtokens=0; - int devscan=0; - - if (!(copy=strdup(line))){ - printout(LOG_INFO,"No memory to parse file: %s line %d, %s\n", CONFIGFILE, lineno, strerror(errno)); - exit(EXIT_NOMEM); - } - - // get first token -- device name - if (!(name=strtok(copy,delim)) || *name=='#') { - free(copy); - return 0; - } - - // Have we detected the DEVICESCAN directive? - if (!strcmp(SCANDIRECTIVE,name)){ - devscan=1; - if (numtokens) { - printout(LOG_INFO,"Scan Directive %s must be the first entry in %s\n",name,CONFIGFILE); - exit(EXIT_BADCONF); - } - else - printout(LOG_INFO,"Scan Directive %s found in %s. Will scan for devices.\n",name,CONFIGFILE); - } - numtokens++; - - // Is there space for another entry? - if (entry>=MAXENTRIES){ - printout(LOG_CRIT,"Error: configuration file %s can have no more than MAXENTRIES=%d entries\n", - CONFIGFILE,MAXENTRIES); - exit(EXIT_CCONST); - } - - // We've got a legit entry, clear structure - cfg=config+entry; - memset(cfg,0,sizeof(*config)); - - // Save info to process memory for after forking 32 bytes contains 1 - // bit per possible attribute ID. See isattoff() - cfg->name=strdup(name); - if (!devscan){ - cfg->monitorattflags=(unsigned char *)calloc(NMONITOR*32,1); - cfg->attributedefs=(unsigned char *)calloc(256,1); - } - - // check that all memory allocations were sucessful - if (!cfg->name || (!devscan && (!cfg->monitorattflags || !cfg->attributedefs))) { - printout(LOG_INFO,"No memory to store file: %s line %d, %s\n", CONFIGFILE, lineno, strerror(errno)); - exit(EXIT_NOMEM); - } - - // Store line number, and by default check for both device types. - cfg->lineno=lineno; - cfg->tryscsi=1; - cfg->tryata=1; - - // Try and recognize if a IDE or SCSI device. These can be - // overwritten by configuration file directives. - if (GUESS_DEVTYPE_ATA == guess_linux_device_type(name)) - cfg->tryscsi=0; - else if (GUESS_DEVTYPE_SCSI == guess_linux_device_type(name)) - cfg->tryata=0; - /* in "don't know" case leave both tryata and tryscsi set */ - - // parse tokens one at a time from the file. This line actually - // parses ALL the tokens. - while ((token=strtok(NULL,delim)) && parsetoken(token,cfg)){ -#if 0 - printout(LOG_INFO,"Parsed token %s\n",token); -#endif - } - - // If no ATA monitoring directives are set, then set all of them. - if (cfg->tryata && !(cfg->smartcheck || cfg->usagefailed || cfg->prefail || - cfg->usage || cfg->selftest || cfg->errorlog)){ - - printout(LOG_INFO,"Drive: %s, implied '-a' Directive on line %d of file %s\n", - cfg->name, cfg->lineno, CONFIGFILE); - - cfg->smartcheck=1; - cfg->usagefailed=1; - cfg->prefail=1; - cfg->usage=1; - cfg->selftest=1; - cfg->errorlog=1; - } - - // additional sanity check. Has user set -M options without -m? - if (!cfg->address && (cfg->emailcmdline || cfg->emailfreq || cfg->emailtest)){ - printout(LOG_CRIT,"Drive: %s, -M Directive(s) on line %d of file %s need -m ADDRESS Directive\n", - cfg->name, cfg->lineno, CONFIGFILE); - Directives(); - exit(EXIT_BADCONF); - } - - // has the user has set <nomailer>? - if (cfg->address && !strcmp(cfg->address,"<nomailer>")){ - // check that -M exec is also set - if (!cfg->emailcmdline){ - printout(LOG_CRIT,"Drive: %s, -m <nomailer> Directive on line %d of file %s needs -M exec Directive\n", - cfg->name, cfg->lineno, CONFIGFILE); - Directives(); - exit(EXIT_BADCONF); - } - // now free memory. From here on the sign of <nomailer> is - // address==NULL and cfg->emailcmdline!=NULL - free(cfg->address); - cfg->address=NULL; - } - - // set cfg->emailfreq to 1 (once) if user hasn't set it - if (!cfg->emailfreq) - cfg->emailfreq = 1; - - entry++; - free(copy); - - // Return: - if (devscan) - return -1; - else - return 1; -} - -// returns number of entries in config file, or 0 if no config file -// exists. A config file with zero entries will cause an error -// message and an exit. Returns -1 if it found a SCANDEVICE directive -// in the config file. -int parseconfigfile(){ - FILE *fp; - int entry=0,lineno=1,cont=0,contlineno=0; - char line[MAXLINELEN+2]; - char fullline[MAXCONTLINE+1]; - - // Open config file, if it exists - fp=fopen(CONFIGFILE,"r"); - if (fp==NULL && errno!=ENOENT){ - // file exists but we can't read it - printout(LOG_CRIT,"%s: Unable to open configuration file %s\n", - strerror(errno),CONFIGFILE); - exit(EXIT_BADCONF); - } - - // No config file - if (fp==NULL) - return 0; - - // configuration file exists - printout(LOG_INFO,"Using configuration file %s\n",CONFIGFILE); - - // parse config file line by line - while (1) { - int len=0,scandevice; - char *lastslash; - char *comment; - char *code; - - // make debugging simpler - memset(line,0,sizeof(line)); - - // get a line - code=fgets(line,MAXLINELEN+2,fp); - - // are we at the end of the file? - if (!code){ - if (cont) { - scandevice=parseconfigline(entry,lineno,fullline); - // See if we found a SCANDEVICE directive - if (scandevice<0) - return -1; - // the final line is part of a continuation line - cont=0; - entry+=scandevice; - } - break; - } - - // input file line number - contlineno++; - - // See if line is too long - len=strlen(line); - if (len>MAXLINELEN){ - char *warn; - if (line[len-1]=='\n') - warn="(including newline!) "; - else - warn=""; - printout(LOG_CRIT,"Error: line %d of file %s %sis more than %d characters.\n", - (int)contlineno,CONFIGFILE,warn,(int)MAXLINELEN); - exit(EXIT_CCONST); - } - - // Ignore anything after comment symbol - if ((comment=index(line,'#'))){ - *comment='\0'; - len=strlen(line); - } - - // is the total line (made of all continuation lines) too long? - if (cont+len>MAXCONTLINE){ - printout(LOG_CRIT,"Error: continued line %d (actual line %d) of file %s is more than %d characters.\n", - lineno, (int)contlineno, CONFIGFILE, (int)MAXCONTLINE); - exit(EXIT_CCONST); - } - - // copy string so far into fullline, and increment length - strcpy(fullline+cont,line); - cont+=len; - - // is this a continuation line. If so, replace \ by space and look at next line - if ( (lastslash=rindex(line,'\\')) && !strtok(lastslash+1," \n\t")){ - *(fullline+(cont-len)+(lastslash-line))=' '; - continue; - } - - // Not a continuation line. Parse it - scandevice=parseconfigline(entry,lineno,fullline); - - // did we find a scandevice directive? - if (scandevice<0) - return -1; - - entry+=scandevice; - lineno++; - cont=0; - } - fclose(fp); - if (entry) - return entry; - - printout(LOG_CRIT,"Configuration file %s contains no devices (like /dev/hda)\n",CONFIGFILE); - exit(EXIT_BADCONF); -} - -// Prints copyright, license and version information -void PrintCopyleft(void){ - char out[CVSMAXLEN]; - debugmode=1; - printhead(); - printout(LOG_INFO,copyleftstring); - printout(LOG_INFO,"CVS version IDs of files used to build this code are:\n"); - printone(out,atacmds_c_cvsid); - printout(LOG_INFO,"%s",out); - printone(out,ataprint_c_cvsid); - printout(LOG_INFO,"%s",out); - printone(out,knowndrives_c_cvsid); - printout(LOG_INFO,"%s",out); - printone(out,scsicmds_c_cvsid); - printout(LOG_INFO,"%s",out); - printone(out,smartd_c_cvsid); - printout(LOG_INFO,"%s",out); - printone(out,utility_c_cvsid); - printout(LOG_INFO,"%s",out); - -} - -/* Returns a pointer to a static string containing a formatted list of the valid - arguments to the option opt or NULL on failure. */ -const char *getvalidarglist(char opt) { - switch (opt) { - case 'r': - return "ioctl[,N], ataioctl[,N], scsiioctl[,N]"; - case 'p': - return "<FILE_NAME>"; - case 'i': - return "<INTEGER_SECONDS>"; - default: - return NULL; - } -} - -/* Prints the message "=======> VALID ARGUMENTS ARE: <LIST> <=======\n", where - <LIST> is the list of valid arguments for option opt. */ -void printvalidarglistmessage(char opt) { - const char *s; - - printout(LOG_CRIT, "=======> VALID ARGUMENTS ARE: "); - if (!(s = getvalidarglist(opt))) - printout(LOG_CRIT, "Error constructing argument list for option %c", opt); - else - printout(LOG_CRIT, (char *)s); - printout(LOG_CRIT, " <=======\n"); -} - -// Parses input line, prints usage message and -// version/license/copyright messages -void ParseOpts(int argc, char **argv){ - extern char *optarg; - extern int optopt, optind, opterr; - int optchar; - int badarg; - char *tailptr; - long lchecktime; - // Please update getvalidarglist() if you edit shortopts - const char *shortopts = "cdDi:p:r:Vh?"; -#ifdef HAVE_GETOPT_LONG - char *arg; - // Please update getvalidarglist() if you edit longopts - struct option longopts[] = { - { "checkonce", no_argument, 0, 'c' }, - { "debug", no_argument, 0, 'd' }, - { "showdirectives", no_argument, 0, 'D' }, - { "interval", required_argument, 0, 'i' }, - { "pidfile", required_argument, 0, 'p' }, - { "report", required_argument, 0, 'r' }, - { "version", no_argument, 0, 'V' }, - { "license", no_argument, 0, 'V' }, - { "copyright", no_argument, 0, 'V' }, - { "help", no_argument, 0, 'h' }, - { "usage", no_argument, 0, 'h' }, - { 0, 0, 0, 0 } - }; -#endif - - opterr=optopt=0; - badarg=FALSE; - - // Parse input options: -#ifdef HAVE_GETOPT_LONG - while (-1 != (optchar = getopt_long(argc, argv, shortopts, longopts, NULL))){ -#else - while (-1 != (optchar = getopt(argc, argv, shortopts))){ -#endif - switch(optchar) { - case 'c': - checkonce = TRUE; - debugmode = TRUE; - break; - case 'd': - debugmode = TRUE; - break; - case 'D': - debugmode = TRUE; - Directives(); - exit(0); - break; - case 'i': - // Period (time interval) for checking - // strtol will set errno in the event of overflow, so we'll check it. - errno = 0; - lchecktime = strtol(optarg, &tailptr, 10); - if (*tailptr != '\0' || lchecktime < 10 || lchecktime > INT_MAX || errno) { - debugmode=1; - printhead(); - printout(LOG_CRIT, "======> INVALID INTERVAL: %s <=======\n", optarg); - printout(LOG_CRIT, "======> INTERVAL MUST BE INTEGER BETWEEN %d AND %d <=======\n", 10, INT_MAX); - printout(LOG_CRIT, "\nUse smartd -h to get a usage summary\n\n"); - exit(EXIT_BADCMD); - } - checktime = (int)lchecktime; - break; - case 'r': - { - int i; - char *s; - - // split_report_arg() may modify its first argument string, so use a - // copy of optarg in case we want optarg for an error message. - if (!(s = strdup(optarg))) { - printout(LOG_CRIT, "Can't allocate memory to copy argument to" - " -r option - exiting\n"); - exit(EXIT_NOMEM); - } - if (split_report_arg(s, &i)) { - badarg = TRUE; - } else if (!strcmp(s,"ioctl")) { - con->reportataioctl = con->reportscsiioctl = i; - } else if (!strcmp(s,"ataioctl")) { - con->reportataioctl = i; - } else if (!strcmp(s,"scsiioctl")) { - con->reportscsiioctl = i; - } else { - badarg = TRUE; - } - free(s); - } - break; - case 'p': - if( -1 == asprintf(&pid_file, "%s", optarg)) { - printout(LOG_CRIT, "Can't allocate memory for pid file name %s - exiting.\n", optarg); - pid_file = NULL; - exit(EXIT_NOMEM); - } - break; - case 'V': - PrintCopyleft(); - exit(0); - break; - case '?': - case 'h': - default: - debugmode=1; - printhead(); -#ifdef HAVE_GETOPT_LONG - // Point arg to the argument in which this option was found. - arg = argv[optind-1]; - // Check whether the option is a long option that doesn't map to -h. - if (arg[1] == '-' && optchar != 'h') { - // Iff optopt holds a valid option then argument must be missing. - if (optopt && (strchr(shortopts, optopt) != NULL)) { - printout(LOG_CRIT, "=======> ARGUMENT REQUIRED FOR OPTION: %s <=======\n",arg+2); - printvalidarglistmessage(optopt); - } else { - printout(LOG_CRIT, "=======> UNRECOGNIZED OPTION: %s <=======\n\n",arg+2); - } - printout(LOG_CRIT, "\nUse smartd --help to get a usage summary\n\n"); - exit(EXIT_BADCMD); - } -#endif - if (optopt) { - // Iff optopt holds a valid option then argument must be missing. - if (strchr(shortopts, optopt) != NULL){ - printout(LOG_CRIT, "=======> ARGUMENT REQUIRED FOR OPTION: %c <=======\n",optopt); - printvalidarglistmessage(optopt); - } else { - printout(LOG_CRIT, "=======> UNRECOGNIZED OPTION: %c <=======\n\n",optopt); - } - printout(LOG_CRIT, "\nUse smartd -h to get a usage summary\n\n"); - exit(EXIT_BADCMD); - } - Usage(); - exit(0); - } - - // Check to see if option had an unrecognized or incorrect argument. - if (badarg) { - debugmode=1; - printhead(); - // It would be nice to print the actual option name given by the user - // here, but we just print the short form. Please fix this if you know - // a clean way to do it. - printout(LOG_CRIT, "=======> INVALID ARGUMENT TO -%c: %s <======= \n", optchar, optarg); - printvalidarglistmessage(optchar); - printout(LOG_CRIT, "\nUse smartd -h to get a usage summary\n\n"); - exit(EXIT_BADCMD); - } - } - - // no pidfile in debug mode - if (debugmode && pid_file) { - printout(LOG_INFO, "warning: pid file %s not written in debug mode\n", pid_file); - free(pid_file); - pid_file = NULL; - } - - // print header - printhead(); - - return; -} - -// Function we call if no configuration file was found or if the -// DEVICESCAN Directive was found. It makes entries for /dev/hd[a-l] -// and /dev/sd[a-z]. -int makeconfigentries(int num, char *name, int isata, int start, int scandirective){ - int i; - - // check that we still have space for entries - if (MAXENTRIES<(start+num)){ - printout(LOG_CRIT,"Error: simulated config file can have no more than %d entries\n",(int)MAXENTRIES); - exit(EXIT_CCONST); - } - - // loop over the number of entries that we should create - for(i=0; i<num; i++){ - cfgfile *cfg=config+start+i; - - // If user has given the scan directive, copy config files entries - if (scandirective){ - memcpy(cfg, config, sizeof(*cfg)); - } - else { - // no config file was used: all structure entries need to be set - memset(cfg,0,sizeof(*cfg)); - - // enable all possible tests - cfg->smartcheck=1; - cfg->prefail=1; - cfg->usagefailed=1; - cfg->usage=1; - cfg->selftest=1; - cfg->errorlog=1; - - // lineno==0 is our clue that the device was not found in a - // config file! - cfg->lineno=0; - } - - // select if it's a SCSI or ATA device - cfg->tryata=isata; - cfg->tryscsi=!isata; - - // put in the device name - cfg->name=strdup(name); - cfg->monitorattflags=(unsigned char *)calloc(NMONITOR*32,1); - cfg->attributedefs=(unsigned char *)calloc(256,1); - if (!cfg->name || !cfg->monitorattflags || !cfg->attributedefs) { - printout(LOG_INFO,"No memory for %d'th device after %s, %s\n", i, name, strerror(errno)); - exit(EXIT_NOMEM); - } - - // increment final character of the name - cfg->name[strlen(name)-1]+=i; - } - return i; -} - -void cantregister(char *name, char *type, int line, int scandirective){ - if (line) - printout(scandirective?LOG_INFO:LOG_CRIT, - "Unable to register %s device %s at line %d of file %s\n", - type, name, line, CONFIGFILE); - else - printout(LOG_INFO,"Unable to register %s device %s\n", - type, name); - return; -} - - -/* Main Program */ -int main (int argc, char **argv){ - atadevices_t atadevices[MAXATADEVICES], *atadevicesptr=atadevices; - scsidevices_t scsidevices[MAXSCSIDEVICES], *scsidevicesptr=scsidevices; - int i, entries, scandirective=0, scanning=0; - smartmonctrl control; - - // initialize global communications variables - con=&control; - memset(con,0,sizeof(control)); - - // Parse input and print header and usage info if needed - ParseOpts(argc,argv); - - // Do we mute printing from ataprint commands? - con->quietmode=0; - con->veryquietmode=debugmode?0:1; - con->checksumfail=0; - - // look in configuration file CONFIGFILE (normally /etc/smartd.conf) - entries=parseconfigfile(); - - // if SCANDEVICE used or there was no /etc/smartd.conf config file, - // then create needed entries for scanning - if (entries<=0){ - int doscsi, doata; - - scanning=1; - - // Was SCANDEVICE Directive given? - scandirective=entries; - if (scandirective){ - printout(LOG_INFO,"smartd: Scanning for devices.\n"); - // free up storage used for SCANDIRECTIVE string - free(config->name); - config->name=NULL; - } - else { - // No config file given, so scan for both ATA and SCSI devices - printout(LOG_INFO,"smartd: file %s not found. Searching for ATA & SCSI devices.\n",CONFIGFILE); - config->tryata=1; - config->tryscsi=1; - } - - // initialize total number of entries to seach for - entries=0; - doata=config->tryata; - doscsi=config->tryscsi; - - // make list of ATA devices to search for - if (doata) - entries+=makeconfigentries(MAXATADEVICES, "/dev/hda", 1, entries, scandirective); - // make list of SCSI devices to search for - if (doscsi) - entries+=makeconfigentries(MAXSCSIDEVICES, "/dev/sda", 0, entries, scandirective); - } - - // Register entries - for (i=0;i<entries;i++){ - int notregistered=1; - - // register ATA devices - if (config[i].tryata){ - if (atadevicescan2(atadevicesptr+numatadevices, config+i)) - cantregister(config[i].name, "ATA", config[i].lineno, scandirective); - else - notregistered=0; - } - - // then register SCSI devices - if (config[i].tryscsi){ - if (scsidevicescan(scsidevicesptr+numscsidevices, config+i, - scandirective)) - cantregister(config[i].name, "SCSI", config[i].lineno, scandirective); - else - notregistered=0; - } - - // if device explictly listed and we can't register it, then exit - if (notregistered && !scanning){ - printout(LOG_CRIT, "Unable to register device %s - exiting.\n", config[i].name); - exit(EXIT_BADDEV); - } - } // done registering entries - - // If there are no devices to monitor, then exit - if (!numatadevices && !numscsidevices){ - printout(LOG_INFO,"Unable to monitor any SMART enabled ATA or SCSI devices.\n"); - exit(EXIT_BADDEV); - } - - // Now start an infinite loop that checks all devices - CheckDevices(atadevicesptr, scsidevicesptr); - return 0; -} - diff --git a/sm5/smartd.conf b/sm5/smartd.conf deleted file mode 100644 index 19a3a16d2..000000000 --- a/sm5/smartd.conf +++ /dev/null @@ -1,65 +0,0 @@ -# /etc/smartd.conf - -# Sample configuration file for smartd. See man 5 smartd.conf. -# Home page is: http://smartmontools.sourceforge.net - -# The file gives a list of devices to monitor using smartd, with one -# device per line. Text after a hash (#) is ignored, and you may use -# spaces and tabs for white space. You may use '\' to continue lines. - -# You can usually identify which hard disks are on your system by -# looking in /proc/ide and in /proc/scsi. - -# The word DEVICESCAN will cause any remaining lines in this -# configuration file to be ignored: it tells smartd to scan for all -# ATA and SCSI devices. DEVICESCAN may be followed by any of the -# Directives listed below, which will be applied to all devices that -# are found. Most users should comment out DEVICESCAN and explicitly -# list the devices that they wish to monitor. -DEVICESCAN - -# First (primary) ATA/IDE hard disk. Monitor all attributes -/dev/hda -a - -# Monitor SMART status, ATA Error Log, Self-test log, and track -# changes in all attributes except for attribute 194 -/dev/hdb -H -l error -l selftest -t -I 194 - -# A very silent check. Only report SMART health status if it fails -# But send an email in this case -/dev/hdc -H -m admin@yoyodyne.com - -# First two SCSI disks. This will monitor everything that smartd can -# monitor. -/dev/sda -d scsi -/dev/sdb -d scsi - -# HERE IS A LIST OF DIRECTIVES FOR THIS CONFIGURATION FILE -# -d TYPE Set the device type to one of: ata, scsi -# -T TYPE set the tolerance to one of: normal, permissive -# -o VAL Enable/disable automatic offline tests (on/off) -# -S VAL Enable/disable attribute autosave (on/off) -# -H Monitor SMART Health Status, report if failed -# -l TYPE Monitor SMART log. Type is one of: error, selftest -# -f Monitor for failure of any 'Usage' Attributes -# -m ADD Send warning email to ADD for -H, -l error, -l selftest, and -f -# -M TYPE Modify email warning behavior (see man page) -# -p Report changes in 'Prefailure' Normalized Attributes -# -u Report changes in 'Usage' Normalized Attributes -# -t Equivalent to -p and -u Directives -# -r ID Also report Raw values of Attribute ID with -p, -u or -t -# -R ID Track changes in Attribute ID Raw value with -p, -u or -t -# -i ID Ignore Attribute ID for -f Directive -# -I ID Ignore Attribute ID for -p, -u or -t Directive -# -v N,ST Modifies labeling of Attribute N (see man page) -# -a Default: equivalent to -H -f -t -l error -l selftest -# -F TYPE Use firmware bug workaround. Type is one of: none, samsung -# -P TYPE Drive-specific presets: use, ignore, show, showall -# # Comment: text after a hash sign is ignored -# \ Line continuation character -# Attribute ID is a decimal integer 1 <= ID <= 255 -# All but -d, -m and -M Directives are only implemented for ATA devices -# -# If the test string DEVICESCAN is the first uncommented text -# then smartd will scan for devices /dev/hd[a-l] and /dev/sd[a-z] -# DEVICESCAN may be followed by any desired Directives. diff --git a/sm5/smartd.conf.5 b/sm5/smartd.conf.5 deleted file mode 100644 index 629d6c35e..000000000 --- a/sm5/smartd.conf.5 +++ /dev/null @@ -1,867 +0,0 @@ -\# Copyright (C) 2002-3 Bruce Allen <smartmontools-support@lists.sourceforge.net> -\# -\# $Id: smartd.conf.5,v 1.47 2003/04/23 13:19:40 guidog Exp $ -\# -\# 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 -\# Software Foundation; either version 2, or (at your option) any later -\# version. -\# -\# You should have received a copy of the GNU General Public License (for -\# example COPYING); if not, write to the Free Software Foundation, Inc., 675 -\# Mass Ave, Cambridge, MA 02139, USA. -\# -\# This code was originally developed as a Senior Thesis by Michael Cornwell -\# at the Concurrent Systems Laboratory (now part of the Storage Systems -\# Research Center), Jack Baskin School of Engineering, University of -\# California, Santa Cruz. http://ssrc.soe.ucsc.edu/ -\# -.TH SMARTD.CONF 5 "$Date: 2003/04/23 13:19:40 $" "smartmontools-5.1" -.SH NAME -smartd.conf \- SMART Disk Monitoring Daemon Configuration File - -.SH DESCRIPTION -.B /etc/smartd.conf -is the configuration file for the -.B smartd -daemon, which -monitors the Self-Monitoring, Analysis and Reporting -Technology (SMART) system built into many ATA-3 and later ATA, -IDE and SCSI-3 hard drives. - -Note that -.B smartd -only reads the configuration file at start-up: changes to the -configuration file take effect only after the -.B smartd -daemon is restarted. If you send a HUP signal to -.B smartd -it will log a polite message saying that it ignores this signal and -that it has -.I not -re-read the configuration file. - -\# DO NOT MODIFY THIS OR THE FOLLOWING TWO LINES. WHAT FOLLOWS -\# IS AUTOMATICALLY INCLUDED FROM THE FILE smartd.8 -\# STARTINCLUDE - -.SH CONFIGURATION FILE /etc/smartd.conf -In the absence of a configuration file, -.B smartd -will try to open the 12 ATA devices -.B /dev/hd[a-l] -and the 26 SCSI devices -.B /dev/sd[a-z]. -This can be annoying if you have an ATA or SCSI device that hangs or -misbehaves when receiving SMART commands. Even if this causes no -problems, you may be annoyed by the string of error log messages about -block-major devices that can't be found, and SCSI devices that can't -be opened. - -One can avoid this problem, and gain more control over the types of -events monitored by -.B smartd, -by using the configuration file -.B /etc/smartd.conf. -This file contains a list of devices to monitor, with one device per -line. An example file is included with the -.B smartmontools -distribution. You will find this sample configuration file in -\fB/usr/share/doc/smartmontools-5.1/\fP. For security, the configuration file -should not be writable by anyone but root. The syntax of the file is as -follows: - -.IP -There should be one device listed per line, although you may have -lines that are entirely comments or white space. - -Any text following a hash sign (#) and up to the end of the line is -taken to be a comment, and ignored. - -Lines may be continued by using a backslash (\(rs) as the last -non-whitespace or non-comment item on a line. - -.PP 0 -.fi -Here is an example configuration file. It's for illustrative purposes -only; please don't copy it onto your system without reading to the end -of the -.B DIRECTIVES -Section below! - -.nf -.B ################################################ -.B # This is an example smartd startup config -.B # file /etc/smartd.conf for monitoring three -.B # ATA disks and two SCSI disks. -.B # -.nf -.B # First ATA disk on each of two interfaces: -.B # -.B \ \ /dev/hda -a -m admin@yoyodyne.com,root@localhost -.B \ \ /dev/hdc -a -I 194 -I 5 -i 12 -.B # -.nf -.B # SCSI disks. Send a TEST warning email to admin on -.B # startup. -.B # -.B \ \ /dev/sda -.B \ \ /dev/sdc -m admin@yoyodyne.com -M test -.B # -.nf -.B # Strange device. It's SCSI: -.B # -.B \ \ /dev/weird -d scsi -.B # -.nf -.B # The following line enables monitoring of the -.B # ATA Error Log and the Self-Test Error Log. -.B # It also tracks changes in both Prefailure -.B # and Usage Attributes, apart from Attributes -.B # 9, 194, and 231, and shows continued lines: -.B # -.B \ \ /dev/hdd\ -l\ error\ \(rs -.B \ \ \ \ \ \ \ \ \ \ \ -l\ selftest\ \(rs -.B \ \ \ \ \ \ \ \ \ \ \ -t\ \(rs\ \ \ \ \ \ # Attributes not tracked: -.B \ \ \ \ \ \ \ \ \ \ \ -I\ 194\ \(rs\ \ # temperature -.B \ \ \ \ \ \ \ \ \ \ \ -I\ 231\ \(rs\ \ # also temperature -.B \ \ \ \ \ \ \ \ \ \ \ -I 9\ \ \ \ \ \ # power-on hours -.B # -.B ################################################ -.fi - -.PP -.SH CONFIGURATION FILE DIRECTIVES -.PP - -If the first non-comment entry in the configuration file is the text -string -.B DEVICESCAN -in capital letters, then -.B smartd -will ignore any remaining lines in the configuration file, and will -scan for devices. -.B DEVICESCAN -may optionally be followed by Directives that will apply to all -devices that are found in the scan. Please see below for additional -details. - -.sp 2 -The following are the Directives that may appear following the device -name or -.B DEVICESCAN -on any line of the -.B /etc/smartd.conf -configuration file. Note that -.B these are NOT command-line options for -.B smartd. -The Directives below may appear in any order, following the device -name. - -.B For an ATA device, -if no Directives appear, then the device will be monitored -as if the '\-a' Directive (monitor all SMART properties) had been given. - -.B If a SCSI disk is listed, -it will be monitored at the only implemented level: roughly equivalent -to using the '\-H' option for an ATA disk. So with the exception of '\-d', '\-m', and '\-M', -the Directives below are ignored for SCSI -disks. For SCSI disks, the '\-m' Directive sends a warning email if -the SMART status indicates a disk failure or problem, or if the SCSI inquiry about disk status fails. - -.TP -.B \-d TYPE -Specifies the type of the device. This will prevent -.B smartd -from issuing SCSI commands to an ATA device and vice versa. The valid -arguments to this Directive are \fIata\fP and \fIscsi\fP. - -In the absence of this Directive, -.B smartd -will first attempt to guess the device type by looking at whether the sixth -character in the device name is an 's' or an 'h'. This will work for -device names like /dev/hda or /dev/sdb. If -.B smartd -can't guess from this sixth character, then it will simply try to -access the device using first ATA and then SCSI ioctl()s. -.TP -.B \-T TYPE -Specifies how tolerant -.B smartd -should be of SMART command failures. The valid arguments to this -Directive are: - -.I normal -\- do not try to monitor the disk if a mandatory SMART command fails, but -continue if an optional SMART command fails. This is the default. - -.I permissive -\- try to monitor the disk even if it appears to lack SMART capabilities. -This may be required for some old disks (prior to ATA-3 revision 4) that -implemented SMART before the SMART standards -were incorporated into the ATA/ATAPI Specifications. - -[Please see the -.B smartctl \-T -command-line option.] -.TP -.B \-o VALUE -Enables or disables SMART Automatic Offline Testing when -.B smartd -starts up and has no further effect. The valid arguments to this -Directive are \fIon\fP and \fIoff\fP. - -The delay between tests is vendor-specific, but is typically four hours. -[Please see the -.B smartctl \-o -command-line option.] -.TP -.B \-S VALUE -Enables or disables Attribute Autosave when -.B smartd -starts up and has no further effect. The valid arguments to this -Directive are \fIon\fP and \fIoff\fP. [Please see the -.B smartctl \-S -command-line option.] -.TP -.B \-H -Check the SMART health status of the disk. If any Prefailure -Attributes are less than or equal to their threshold values, then disk -failure is predicted in less than 24 hours, and a message at priority -.B 'CRITICAL' -will be logged to syslog. [Please see the -.B smartctl \-H -command-line option.] -.TP -.B \-l TYPE -Reports increases in the number of errors in one of the two SMART logs. The -valid arguments to this Directive are: - -.I error -\- report if that the number of ATA errors reported in the ATA Error Log has -increased since the last check. - -.I selftest -\- report if that the number of errors reported in the SMART Self-Test Log -has increased since the last check. Note that such errors will -.B only -be logged if you run self-tests on the disk (and it fails the tests!). -[Self-Tests can be run by using the -.B '\-t\ short' -and -.B '\-t\ long' -options of -.B smartctl -and the results of the testing can be observed using the -.B smartctl '\-l\ selftest' -command-line option.] - -[Please see the -.B smartctl \-l -command-line option.] -.TP -.B \-f -Check for 'failure' of any Usage Attributes. If these -Attributes are less than or equal to the threshold, it does NOT -indicate imminent disk failure. It ""indicates an advisory condition -where the usage or age of the device has exceeded its intended design -life period."" [Please see the -.B smartctl \-A -command-line option.] - -.TP -.B \-m ADD -Send a warning email to the email address -.B ADD -if the '\-H', '\-l', or '\-f' Directives detect a failure or a new -error, or is a SMART command to the disk fails. This Directive only -works in conjunction with these other Directives (or with the -equivalent default '\-a' Directive). - -To prevent your email in-box from getting filled up with warning -messages, by default only a single warning will be sent for each of -the enabled test types, '\-H', '\-l', or '\-f', even if more than one -failure or error is detected or if the failure or error persists. -[This behavior can be modified; see the '\-M' Directive below.] - -To send email to more than one user, please use the following form for -the address: -.B user1@add1,user2@add2,...,userN@addN -(with no spaces). - -To test that email is being sent correctly, use the '\-M test' -Directive described below to send one test email message on -.B smartd -startup. - -By default, email is sent using the system -.B mail -command. In order that -.B smartd -find the mail command (normally /bin/mail) an executable named -.B 'mail' -must be in the path of the shell or environment from which -.B smartd -was started. If you wish to specify an explicit path to the mail -executable (for example /usr/local/bin/mail) or a custom script to -run, please use the '\-M exec' Directive below. - -Note that there is a special argument -.B <nomailer> -which can be given to the '\-m' Directive in conjunction with the '\-M -exec' Directive. Please see below for an explanation of its effect. - -.TP -.B \-M TYPE -These Directives modify the behavior of the -.B smartd -email warnings enabled with the '\-m' email Directive described above. -These '\-M' Directives only work in conjunction with the '\-m' -Directive and can not be used without it. - -Multiple \-M Directives may be given. If conflicting \-M Directives -are given (example: \-M once \-M daily) then the final one (in the -example, \-M daily) is used. - -The valid arguments to the \-M Directive are: - -.I once -\- send only one warning email for each type of disk problem detected. This -is the default. - -.I daily -\- send additional warning reminder emails, once per day, for each type -of disk problem detected. - -.I diminishing -\- send additional warning reminder emails, after a one-day interval, -then a two-day interval, then a four-day interval, and so on for each -type of disk problem detected. Each interval is twice as long as the -previous interval. - -.I test -\- send a single test email -immediately upon -.B smartd -startup. This allows one to verify that any email is correctly delivered. - -.I exec PATH -\- run the executable PATH instead of the default mail command, when -.B smartd -needs to send email. PATH must point to an executable binary file or -script. - -By setting PATH to point to a customized script, you can make -.B smartd -perform useful tricks when a disk problem is detected (beeping the -console, shutting down the machine, broadcasting warnings to all -logged-in users, etc.) But please be careful. -.B smartd -will -.B block -until the executable PATH returns, so if your executable hangs, then -.B smartd -will also hang. Some sample scripts are included in -/usr/share/doc/smartmontools-5.1/examplescripts/. - -The return status of the executable is recorded by -.B smartd -in SYSLOG, but the executable's STDOUT and STDERR are directed to -/dev/null, so if you wish to leave some other record behind, the -executable must send mail or write to a file or device. - -Before running the executable, -.B smartd -sets a number of environment variables. These environment variables -may be used to control the executable's behavior. The environment -variables exported by -.B smartd -are: -.nf -.fi -.B SMARTD_MAILER -is set to the argument of -M exec, if present or else to 'mail' -(examples: /bin/mail, mail). -.nf -.fi -.B SMARTD_DEVICE -is set to the device path (examples: /dev/hda, /dev/sdb). -.nf -.fi -.B SMARTD_DEVICETYPE -is set to the device type (possible values: ata, scsi). -.nf -.fi -.B SMARTD_FAILTYPE -gives the reason for the warning or message email. The possible values that -it takes, and their significance, are: -.I emailtest -(this is an email test message); -.I health -(the SMART health status indicates imminent failure); -.I usage -(a usage Attribute has failed); -.I selftest -(the number of self-test failures has increased); -.I errorcount -(the number of errors in the ATA error log has increased); -.I FAILEDhealthcheck -(the SMART health status command failed); -.I FAILEDreadsmartdata -(the command to read SMART Attribute data failed); -.I FAILEDreadsmarterrorlog -(the command to read the SMART error log failed); -.I FAILEDreadsmartsefltestlog -(the command to read the SMART self-test log failed); abd -.I FAILEDopendevice -(the open() command to the device failed). -.nf -.fi -.B SMARTD_ADDRESS -is set to the address argument ADD of the '\-m' Directive, unless ADD -is -.B <nomailer>. -This is a comma-delineated list of email addresses (example: -admin@yoyodyne.com). -.nf -.fi -.B SMARTD_MESSAGE -is set to the warning email message string from -.B smartd. -This message string contains space characters and is NOT quoted. So to -use $SMARTD_MESSAGE in a bash script you should probably enclose it in -double quotes. -.nf -.fi -.B SMARTD_TFIRST -is a text string giving the time and date at which the first problem -of this type was reported. This text string contains space characters -and no newlines, and is NOT quoted. For example: -.nf -.fi -Sun Feb 9 14:58:19 2003 CST -.nf -.fi -.B SMARTD_TFIRSTEPOCH -is an integer, which is the unix epoch (number of seconds since Jan 1, -1970) for -.B SMARTD_TFIRST. - -The shell which is used to run PATH is system-dependent. For vanilla -linux/glibc it's bash. For other systems, the man page for system (3) -should say what shell is used. - -If the '\-m ADD' Directive is given with a normal address argument, -then the executable pointed to by PATH will be run in a shell with -STDIN receiving the body of the email message, and with the same -command-line arguments: -.nf --s \(dq$SMARTD_SUBJECT\(dq $SMARTD_ADDRESS -.fi -that would normally be provided to 'mail'. Examples include: -.nf -.B -m user@home -M exec /bin/mail -.B -m admin@work -M exec /usr/local/bin/mailto -.B -m root -M exec /Example_1/bash/script/below -.fi - -If the '\-m ADD' Directive is given with the special address argument -.B <nomailer> -then the executable pointed to by PATH is run in a shell with -.B no -STDIN and -.B no -command-line arguments, for example: -.nf -.B -m <nomailer> -M exec /Example_2/bash/script/below -.fi - -Some EXAMPLES of scripts that can be used with the '\-M exec' -Directive are given below. Some sample scripts are also included in -/usr/share/doc/smartmontools-5.1/examplescripts/. - -.TP -.B \-p -Report anytime that a Prefail Attribute has changed -its value since the last check, 30 minutes ago. [Please see the -.B smartctl \-A -command-line option.] -.TP -.B \-u -Report anytime that a Usage Attribute has changed its value -since the last check, 30 minutes ago. [Please see the -.B smartctl \-A -command-line option.] -.TP -.B \-t -Equivalent to turning on the two previous flags '\-p' and '\-u'. -Tracks changes in -.I all -device Attributes (both Prefailure and Usage). [Please see the -.B smartctl \-A -command-line option.] -.TP -.B \-i ID -Ignore device Attribute number -.B ID -when checking for failure of Usage Attributes. -.B ID -must be a decimal integer in the range from 1 to 255. This Directive -modifies the behavior of the '\-f' Directive and has no effect without -it. - -This is useful, for example, if you have a very old disk and don't want to keep -getting messages about the hours-on-lifetime Attribute (usually Attribute 9) -failing. This Directive may appear multiple times for a single device, if you -want to ignore multiple Attributes. -.TP -.B \-I ID -Ignore device Attribute -.B ID -when tracking changes in the Attribute values. -.B ID -must be a decimal integer in the range from 1 to 255. This Directive modifies -the behavior of the '\-p', '\-u', and '\-t' tracking Directives and has no effect -without one of them. - -This is useful, for example, if one of the device Attributes is the disk -temperature (usually Attribute 194 or 231). It's annoying to get reports -each time the temperature changes. This Directive may appear multiple -times for a single device, if you want to ignore multiple Attributes. -.TP -.B \-r ID -When tracking, report the -.I Raw -value of Attribute -.B ID -along with its (normally reported) -.I Normalized -value. -.B ID -must be a decimal integer in the range from 1 to 255. This Directive modifies -the behavior of the '\-p', '\-u', and '\-t' tracking Directives and has no effect -without one of them. This Directive may be given multiple times. - -A common use of this Directive is to track the device Temperature -(often ID=194 or 231). - -.TP -.B \-R ID -When tracking, -report whenever the -.I Raw -value of Attribute -.B ID -changes. (Normally -.B smartd -only tracks/reports changes of the -.I Normalized -Attribute values.) -.B ID -must be a decimal integer in the range from 1 to 255. This Directive -modifies the behavior of the '\-p', '\-u', and '\-t' tracking Directives and -has no effect without one of them. This Directive may be given -multiple times. - -If this Directive is given, it automatically implies the '\-r' -Directive for the same Attribute, so that the Raw value of the -Attribute is reported. - -A common use of this Directive is to track the device Temperature -(often ID=194 or 231). It is also useful for understanding how -different types of system behavior affects the values of certain -Attributes. - -.TP -.B \-F TYPE, \-\-firmwarebug=TYPE -Modifies the behavior of -.B smartctl -to compensate for some known and understood device firmware bug. The -valid arguments to this option are: - -.I none -Assume that the device firmware obeys the ATA specifications. This is -the default. - -.I samsung -In some Samsung disks (example: model SV4012H Firmware Version: -RM100-08) some of the two- and four-byte quantities in the SMART data -structures are byte-swapped (relative to the ATA specification). -Enabling this option tells -.B smartctl -to evaluate these quantities in byte-reversed order. Some signs that -your disk needs this option are (1) no self-test log printed, even -though you have run self-tests; (2) very large numbers of ATA errors -reported in the ATA erorr log; (3) strange and impossible values for -the ATA error log timestamps. - -[Please see the -.B smartctl \-F -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: - -.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 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. - -.I 200,writeerrorcount -\- Raw Attribute number 200 is the Write Error 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: -http://coredump.free.fr/linux/hddtemp.db - -.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 \-P TYPE -Specifies whether -.B smartd -should use any preset options that are available for this drive. The -valid arguments to this Directive are: - -.I use -\- use any presets that are available for this drive. This is the default. - -.I ignore -\- do not use any presets for this drive. - -.I show -\- show the presets listed for this drive in the database. - -.I showall -\- show the presets that are available for all drives and then exit. - -[Please see the -.B smartctl \-P -command-line option.] - -.TP -.B \-a -Equivalent to turning on all of the following Directives: -.B '\-H' -to check the SMART health status, -.B '\-f' -to report failures of Usage (rather than Prefail) Attributes, -.B '\-t' -to track changes in both Prefailure and Usage Attributes, -.B '\-l\ selftest' -to report increases in the number of Self-Test Log errors, and -.B '\-l\ error' -to report increases in the number of ATA errors. - -Note that \-a is the default for ATA devices. If none of these other -Directives is given, then \-a is assumed. - -.TP -.B # -Comment: ignore the remainder of the line. -.TP -.B \(rs -Continuation character: if this is the last non-white or non-comment -character on a line, then the following line is a continuation of the current -one. -.PP -If you are not sure which Directives to use, I suggest experimenting -for a few minutes with -.B smartctl -to see what SMART functionality your disk(s) support(s). If you do -not like voluminous syslog messages, a good choice of -.B smartd -configuration file Directives might be: -.nf -.B \-H \-l\ selftest \-l\ error \-f. -.fi -If you want more frequent information, use: -.B -a. - -.TP -.B ADDITIONAL DETAILS ABOUT DEVICESCAN -If the first non-comment entry in the configuration file is the text -string -.B DEVICESCAN -in capital letters, then -.B smartd -will ignore any remaining lines in the configuration file, and will -scan for devices. - -If -.B DEVICESCAN -is not followed by any Directives, then smartd will scan for both ATA -and SCSI devices, and will monitor all possible SMART properties of -any devices that are found. - -.B DEVICESCAN -may optionally be followed by any valid Directives, which will be -applied to all devices that are found in the scan. For example -.nf -.B DEVICESCAN -m root@yoyodyne.com -.fi -will scan for all devices, and then monitor them. It will send one -email warning per device for any problems that are found. -.nf -.B DEVICESCAN -d ata -m root@yoyodyne.com -.fi -will do the same, but restricts the scan to ATA devices only. -.nf -.B DEVICESCAN -H -d ata -m root@yoyodyne.com -.fi -will do the same, but only monitors the SMART health status of the -devices, (rather than the default \-a, which monitors all SMART -properties). - -.TP -.B EXAMPLES OF SHELL SCRIPTS FOR '\-M exec' -These are two examples of shell scripts that can be used with the '\-M -exec PATH' Directive described previously. The paths to these scripts -and similar executables is the PATH argument to the '\-M exec PATH' -Directive. - -Example 1: This script is for use with '\-m ADDRESS -M exec PATH'. It appends -the output of -.B smartctl -a -to the output of the smartd email warning message and sends it to ADDRESS. - -.nf -.B #! /bin/bash - -.B # Save the email message (STDIN) to a file: -.B cat > /root/msg - -.B # Append the output of smartctl -a to the message: -.B /usr/sbin/smartctl -a $SMARTD_DEVICE >> /root/msg - -.B # Now email the message to the user at address ADD: -.B /bin/mail -s \(dq$SMARTD_SUBJECT\(dq $SMARTD_ADDRESS < /root/msg -.fi - -Example 2: This script is for use with '\-m <nomailer> \-M exec -PATH'. It warns all users about a disk problem, waits 30 seconds, and -then powers down the machine. - -.nf -.B #! /bin/bash - -.B # Warn all users of a problem -.B wall 'Problem detected with disk: ' $SMARTD_DEVICE -.B wall 'Warning message from smartd is: ' \(dq$SMARTD_MESSAGE\(dq -.B wall 'Shutting down machine in 30 seconds... ' - -.B # Wait half a minute -.B sleep 30 - -.B # Power down the machine -.B /usr/sbin/shutdown -hf now -.fi - -Some example scripts are distributed with the smartmontools package, -in /usr/share/doc/smartmontools-5.1/examplescripts/. - -Please note that these scripts typically run as root, so any files -that they read/write should not be writable by ordinary users or -reside in directories like /tmp that are writable by ordinary users -and may expose your system to symlink attacks. - -\# ENDINCLUDE -\# DO NOT MODIFY THIS OR PREVIOUS/NEXT LINES. THIS DEFINES THE -\# END OF THE INCLUDED SECTION FROM smartd.8 - -.PP -.SH AUTHOR -Bruce Allen -.B smartmontools-support@lists.sourceforge.net -.fi -University of Wisconsin - Milwaukee Physics Department - -.PP -.SH CREDITS -.fi -This code was derived from the smartsuite package, written by Michael -Cornwell, and from the previous ucsc smartsuite package. It extends -these to cover ATA-5 disks. This code was originally developed as a -Senior Thesis by Michael Cornwell at the Concurrent Systems Laboratory -(now part of the Storage Systems Research Center), Jack Baskin School -of Engineering, University of California, Santa -Cruz. http://ssrc.soe.ucsc.edu/. -.SH -HOME PAGE FOR SMARTMONTOOLS: -.fi -Please see the following web site for updates, further documentation, bug -reports and patches: -.nf -.B -http://smartmontools.sourceforge.net/ - -.SH -SEE ALSO: -.B smartd -(8), -.B smartctl -(8), -.B syslogd -(8) - - - -.SH -CVS ID OF THIS PAGE: -$Id: smartd.conf.5,v 1.47 2003/04/23 13:19:40 guidog Exp $ diff --git a/sm5/smartd.cpp b/sm5/smartd.cpp deleted file mode 100644 index 7c9609883..000000000 --- a/sm5/smartd.cpp +++ /dev/null @@ -1,2180 +0,0 @@ -/* - * Home page of code is: http://smartmontools.sourceforge.net - * - * Copyright (C) 2002-3 Bruce Allen <smartmontools-support@lists.sourceforge.net> - * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org> - * - * 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 Software Foundation; either version 2, or (at your option) - * any later version. - * - * You should have received a copy of the GNU General Public License - * (for example COPYING); if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * This code was originally developed as a Senior Thesis by Michael Cornwell - * at the Concurrent Systems Laboratory (now part of the Storage Systems - * Research Center), Jack Baskin School of Engineering, University of - * California, Santa Cruz. http://ssrc.soe.ucsc.edu/ - * - */ - -#define _GNU_SOURCE -#include <stdio.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/wait.h> -#include <unistd.h> -#include <fcntl.h> -#include <string.h> -#include <linux/hdreg.h> -#include <syslog.h> -#include <stdarg.h> -#include <signal.h> -#include <stdlib.h> -#include <errno.h> -#include <string.h> -#include <time.h> -#include <limits.h> -#ifdef HAVE_GETOPT_H -#include <getopt.h> -#endif -#include "atacmds.h" -#include "ataprint.h" -#include "extern.h" -#include "knowndrives.h" -#include "scsicmds.h" -#include "smartd.h" -#include "utility.h" - -extern const char *atacmds_c_cvsid, *ataprint_c_cvsid, *knowndrives_c_cvsid, *scsicmds_c_cvsid, *utility_c_cvsid; -const char *smartd_c_cvsid="$Id: smartd.cpp,v 1.158 2003/04/26 11:20:22 ballen4705 Exp $" -ATACMDS_H_CVSID ATAPRINT_H_CVSID EXTERN_H_CVSID KNOWNDRIVES_H_CVSID SCSICMDS_H_CVSID SMARTD_H_CVSID UTILITY_H_CVSID; - -// Forward declaration -const char *getvalidarglist(char opt); - -// global variable used for control of printing, passing arguments, etc. -smartmonctrl *con=NULL; - -// Two other globals -- number of ATA and SCSI devices being monitored -int numatadevices=0; -int numscsidevices=0; - -// How long to sleep between checks. Handy as global variable for -// debugging -int checktime=CHECKTIME; - -// name of PID file (== NULL if no pid_file is used) -char* pid_file=NULL; - -// If set, we should exit after checking all disks once -int checkonce=0; - -// Needed to interrupt sleep when catching SIGUSR1. Unix Gurus: I -// know that this can be done better. Please tell me how -- use email -// address for Bruce Allen at the top of this file. Search for -// "sleeptime" to see what I am doing. -volatile int sleeptime=CHECKTIME; - -// Interrupt sleep if we get a SIGUSR1. Unix Gurus: I know that this -// can be done better. Please tell me how -- use email address for -// Bruce Allen at the top of this file. Search for "sleeptime" to see -// what I am doing. -void sleephandler(int sig){ - int oldsleeptime=sleeptime; - sleeptime=0; - printout(LOG_CRIT,"Signal USR1 - checking devices now rather than in %d seconds.\n",oldsleeptime<0?0:oldsleeptime); - return; -} - -// Global Variables for command line options. These should go into a -// structure at some point. -unsigned char debugmode = FALSE; - -// This function prints either to stdout or to the syslog as needed - -// [From GLIBC Manual: Since the prototype doesn't specify types for -// optional arguments, in a call to a variadic function the default -// argument promotions are performed on the optional argument -// values. This means the objects of type char or short int (whether -// signed or not) are promoted to either int or unsigned int, as -// appropriate.] -void printout(int priority,char *fmt, ...){ - va_list ap; - // initialize variable argument list - va_start(ap,fmt); - if (debugmode) - vprintf(fmt,ap); - else { - openlog("smartd",LOG_PID,LOG_DAEMON); - vsyslog(priority,fmt,ap); - closelog(); - } - va_end(ap); - return; -} - -// If either address or executable path is non-null then send and log -// a warning email, or execute executable -void printandmail(cfgfile *cfg, int which, int priority, char *fmt, ...){ - char command[2048], message[256], hostname[256], additional[256]; - char original[256], further[256], domainname[256], subject[256],dates[64]; - int status; - time_t epoch; - va_list ap; - const int day=24*3600; - int days=0; - char *whichfail[]={ - "emailtest", // 0 - "health", // 1 - "usage", // 2 - "selftest", // 3 - "errorcount" // 4 - "FAILEDhealthcheck", //5 - "FAILEDreadsmartdata", //6 - "FAILEDreadsmarterrorlog", //7 - "FAILEDreadsmartsefltestlog",//8 - "FAILEDopendevice" //9 - }; - - char *address=cfg->address; - char *executable=cfg->emailcmdline; - mailinfo *mail=cfg->maildata+which; - - // See if user wants us to send mail - if (!address && !executable) - return; - - // checks for sanity - if (cfg->emailfreq<1 || cfg->emailfreq>3) { - printout(LOG_INFO,"internal error in printandmail(): cfg->emailfreq=%d\n",cfg->emailfreq); - return; - } - if (which<0 || which>9) { - printout(LOG_INFO,"internal error in printandmail(): which=%d\n",which); - return; - } - - // Return if a single warning mail has been sent. - if ((cfg->emailfreq==1) && mail->logged) - return; - - // To decide if to send mail, we need to know what time it is. - epoch=time(NULL); - - // Return if less than one day has gone by - if (cfg->emailfreq==2 && mail->logged && epoch<(mail->lastsent+day)) - return; - - // Return if less than 2^(logged-1) days have gone by - if (cfg->emailfreq==3 && mail->logged){ - days=0x01<<(mail->logged-1); - days*=day; - if (epoch<(mail->lastsent+days)) - return; - } - - // record the time of this mail message, and the first mail message - if (!mail->logged) - mail->firstsent=epoch; - mail->lastsent=epoch; - - // get system host & domain names (not null terminated if length=MAX) - if (gethostname(hostname, 256)) - sprintf(hostname,"Unknown host"); - else - hostname[255]='\0'; - if (getdomainname(domainname, 256)) - sprintf(hostname,"Unknown domain"); - else - domainname[255]='\0'; - - // print warning string into message - va_start(ap, fmt); - vsnprintf(message, 256, fmt, ap); - va_end(ap); - - // appropriate message about further information - additional[0]=original[0]=further[0]='\0'; - if (which) { - sprintf(further,"You can also use the smartctl utility for further investigation.\n"); - - switch (cfg->emailfreq){ - case 1: - sprintf(additional,"No additional email messages about this problem will be sent.\n"); - break; - case 2: - sprintf(additional,"Another email message will be sent in 24 hours if the problem persists.\n"); - break; - case 3: - sprintf(additional,"Another email message will be sent in %d days if the problem persists\n", - (0x01)<<mail->logged); - break; - } - if (cfg->emailfreq>1 && mail->logged){ - dateandtimezoneepoch(dates, mail->firstsent); - sprintf(original,"The original email about this issue was sent at %s\n", dates); - } - } - - snprintf(subject, 256,"SMART error (%s) detected on host: %s", whichfail[which], hostname); - - // If the user has set cfg->emailcmdline, use that as mailer, else "mail". - if (!executable) - executable="mail"; - - // Export information in environment variables that will be useful - // for user scripts - setenv("SMARTD_MAILER", executable, 1); - setenv("SMARTD_DEVICE", cfg->name, 1); - setenv("SMARTD_DEVICETYPE", cfg->tryata?"ata":"scsi", 1); - setenv("SMARTD_MESSAGE", message, 1); - setenv("SMARTD_SUBJECT", subject, 1); - dateandtimezoneepoch(dates, mail->firstsent); - setenv("SMARTD_TFIRST", dates, 1); - snprintf(dates, 64,"%d", (int)mail->firstsent); - setenv("SMARTD_TFIRSTEPOCH", dates, 1); - setenv("SMARTD_FAILTYPE", whichfail[which], 1); - if (address) - setenv("SMARTD_ADDRESS", address, 1); - - // now construct a command to send this as EMAIL - if (address) - snprintf(command, 2048, - "$SMARTD_MAILER -s '%s' %s > /dev/null 2> /dev/null << \"ENDMAIL\"\n" - "This email was generated by the smartd daemon running on host:\n" - "%s\n" - "in the domain:\n" - "%s\n\n" - "The following warning/error was logged by the smartd daemon:\n" - "%s\n\n" - "For details see the SYSLOG (default: /var/log/messages) for host:\n" - "%s\n\n" - "%s%s%s" - "ENDMAIL\n", - subject, address, hostname, domainname, message, hostname, further, original, additional); - else - snprintf(command, 2048, "%s", executable); - - // tell SYSLOG what we are about to do... - printout(LOG_INFO,"%s %s to %s ...\n", - which?"Sending warning via ":"Executing test of", executable, address?address:"<nomailer>"); - - // issue the command to send mail or to run the user's executable - status=system(command); - - // now tell SYSLOG what happened. - if (status==-1){ - printout(LOG_CRIT,"%s %s to %s failed (unable to fork new process)\n", - which?"Warning via":"Test of", executable, address?address:"<nomailer>"); - } - else { - int status8; - // check and report exit status of command -#ifdef WEXITSTATUS - status8=WEXITSTATUS(status); -#else - status8=(status>>8) & 0xff; -#endif - if (status8) - printout(LOG_CRIT,"%s %s to %s failed (32-bit/8-bit exit status: %d/%d)\n", - which?"Warning via":"Test of", executable, address?address:"<nomailer>", status, status8); - else - printout(LOG_INFO,"%s %s to %s successful\n", - which?"Warning via":"Test of", executable, address?address:"<nomailer>"); - } - // increment mail sent counter - mail->logged++; - - return; -} - -// Printing function for watching ataprint commands, or losing them -void pout(char *fmt, ...){ - va_list ap; - // initialize variable argument list - va_start(ap,fmt); - // in debug==1 mode we will print the output from the ataprint.o functions! - if (debugmode && debugmode!=2) - vprintf(fmt,ap); - // in debug==2 mode we print output from knowndrives.o functions - else if (debugmode==2 || con->reportataioctl || con->reportscsiioctl) { - openlog("smartd", LOG_PID, LOG_DAEMON); - vsyslog(LOG_INFO, fmt, ap); - closelog(); - } - va_end(ap); - fflush(NULL); - return; -} - -// tell user that we ignore HUP signals -void huphandler(int sig){ - printout(LOG_CRIT,"HUP ignored: smartd does NOT re-read /etc/smartd.conf.\n"); - return; -} - -// signal handler that tells users about signals that were caught -void sighandler(int sig){ - printout(LOG_CRIT,"smartd received signal %d: %s\n", - sig, strsignal(sig)); - exit(EXIT_SIGNAL); -} - -// remove the PID file -void remove_pid_file(){ - if (pid_file) { - if ( -1==unlink(pid_file) ) - printout(LOG_INFO,"Can't unlink PID file %s (%s).\n", - pid_file, strerror(errno)); - free(pid_file); - } - return; -} - -// signal handler that prints goodbye message and removes pidfile -void goodbye(){ - printout(LOG_CRIT,"smartd is exiting\n"); - remove_pid_file(); - return; -} - -// Forks new process, closes all file descriptors, redirects stdin, -// stdout, stderr -void daemon_init(){ - pid_t pid; - int i; - - // flush all buffered streams. Else we might get two copies of open - // streams since both parent and child get copies of the buffers. - fflush(NULL); - - if ((pid=fork()) < 0) { - // unable to fork! - printout(LOG_CRIT,"smartd unable to fork daemon process!\n"); - exit(EXIT_STARTUP); - } - else if (pid) - // we are the parent process -- exit cleanly - exit(0); - - // from here on, we are the child process. - setsid(); - - // Fork one more time to avoid any possibility of having terminals - if ((pid=fork()) < 0) { - // unable to fork! - printout(LOG_CRIT,"smartd unable to fork daemon process!\n"); - exit(EXIT_STARTUP); - } - else if (pid) - // we are the parent process -- exit cleanly - exit(0); - - // Now we are the child's child... - - // close any open file descriptors - for (i=getdtablesize();i>=0;--i) - close(i); - - // redirect any IO attempts to /dev/null for stdin - i=open("/dev/null",O_RDWR); - // stdout - dup(i); - // stderr - dup(i); - umask(0); - chdir("/"); - - return; -} - -// create a PID file containing the current process id -void write_pid_file() { - if (pid_file) { - int error = 0; - pid_t pid = getpid(); - mode_t old_umask; - FILE* fp; - - old_umask = umask(0077); - fp = fopen(pid_file, "w"); - umask(old_umask); - if (fp == NULL) { - error = 1; - } else if (fprintf(fp, "%d\n", pid) <= 0) { - error = 1; - } else if (fclose(fp) != 0) { - error = 1; - } - if (error) { - printout(LOG_CRIT, "unable to write PID file %s - exiting.\n", pid_file); - exit(EXIT_PID); - } - printout(LOG_INFO, "file %s written containing PID %d\n", pid_file, pid); - } - return; -} - -// Prints header identifying version of code and home -void printhead(){ - printout(LOG_INFO,"smartd version %d.%d-%d Copyright (C) 2002-3 Bruce Allen\n", - (int)RELEASE_MAJOR, (int)RELEASE_MINOR, (int)SMARTMONTOOLS_VERSION); - printout(LOG_INFO,"Home page is %s\n\n",PROJECTHOME); - return; -} - - -// prints help info for configuration file Directives -void Directives() { - printout(LOG_INFO,"Configuration file (/etc/smartd.conf) Directives (after device name):\n"); - printout(LOG_INFO," -d TYPE Set the device type to one of: ata, scsi\n"); - printout(LOG_INFO," -T TYPE set the tolerance to one of: normal, permissive\n"); - printout(LOG_INFO," -o VAL Enable/disable automatic offline tests (on/off)\n"); - printout(LOG_INFO," -S VAL Enable/disable attribute autosave (on/off)\n"); - printout(LOG_INFO," -H Monitor SMART Health Status, report if failed\n"); - printout(LOG_INFO," -l TYPE Monitor SMART log. Type is one of: error, selftest\n"); - printout(LOG_INFO," -f Monitor 'Usage' Attributes, report failures\n"); - printout(LOG_INFO," -m ADD Send email warning to address ADD\n"); - printout(LOG_INFO," -M TYPE Modify email warning behavior (see man page)\n"); - printout(LOG_INFO," -p Report changes in 'Prefailure' Attributes\n"); - printout(LOG_INFO," -u Report changes in 'Usage' Attributes\n"); - printout(LOG_INFO," -t Equivalent to -p and -u Directives\n"); - printout(LOG_INFO," -r ID Also report Raw values of Attribute ID with -p, -u or -t\n"); - printout(LOG_INFO," -R ID Track changes in Attribute ID Raw value with -p, -u or -t\n"); - printout(LOG_INFO," -i ID Ignore Attribute ID for -f Directive\n"); - printout(LOG_INFO," -I ID Ignore Attribute ID for -p, -u or -t Directive\n"); - printout(LOG_INFO," -v N,ST Modifies labeling of Attribute N (see man page) \n"); - printout(LOG_INFO," -P TYPE Drive-specific presets: use, ignore, show, showall\n"); - printout(LOG_INFO," -a Default: equivalent to -H -f -t -l error -l selftest\n"); - printout(LOG_INFO," -F TYPE Use firmware bug workaround. Type is one of: none, samsung\n"); - printout(LOG_INFO," # Comment: text after a hash sign is ignored\n"); - printout(LOG_INFO," \\ Line continuation character\n"); - printout(LOG_INFO,"Attribute ID is a decimal integer 1 <= ID <= 255\n"); - printout(LOG_INFO,"SCSI devices: only -d, -m, and -M Directives allowed.\n"); - printout(LOG_INFO,"Example: /dev/hda -a\n"); -return; -} - -/* prints help information for command syntax */ -void Usage (void){ - printout(LOG_INFO,"Usage: smartd [options]\n\n"); -#ifdef HAVE_GETOPT_LONG - printout(LOG_INFO," -c, --checkonce\n"); - printout(LOG_INFO," Check all devices once, then exit\n\n"); - printout(LOG_INFO," -d, --debug\n"); - printout(LOG_INFO," Start smartd in debug mode\n\n"); - printout(LOG_INFO," -D, --showdirectives\n"); - printout(LOG_INFO," Print the configuration file Directives and exit\n\n"); - printout(LOG_INFO," -h, -?, --help, --usage\n"); - printout(LOG_INFO," Display this help and exit\n\n"); - printout(LOG_INFO," -i N, --interval=N\n"); - printout(LOG_INFO," Set interval between disk checks to N seconds, where N >= 10\n\n"); - printout(LOG_INFO," -p NAME, --pidfile=NAME\n"); - printout(LOG_INFO," Write PID file NAME\n\n"); - printout(LOG_INFO," -r, --report=TYPE\n"); - printout(LOG_INFO," Report transactions for one of: %s\n\n", getvalidarglist('r')); - printout(LOG_INFO," -V, --version, --license, --copyright\n"); - printout(LOG_INFO," Print License, Copyright, and version information\n"); -#else - printout(LOG_INFO," -c Check all devices once, then exit\n"); - printout(LOG_INFO," -d Start smartd in debug mode\n"); - printout(LOG_INFO," -D Print the configuration file Directives and exit\n"); - printout(LOG_INFO," -h Display this help and exit\n"); - printout(LOG_INFO," -i N Set interval between disk checks to N seconds, where N >= 10\n"); - printout(LOG_INFO," -p NAME Write PID file NAME\n"); - printout(LOG_INFO," -r TYPE Report transactions for one of: %s\n", getvalidarglist('r')); - printout(LOG_INFO," -V Print License, Copyright, and version information\n"); - printout(LOG_INFO," -? Same as -h\n"); -#endif -} - -// returns negative if problem, else fd>=0 -static int opendevice(char *device, int flags) -{ - int fd; - - fd = open(device, flags); - if (fd < 0) { - printout(LOG_INFO,"Device: %s, %s, open() failed\n", - device, strerror(errno)); - return -1; - } - // device opened sucessfully - return fd; -} - -int closedevice(int fd, char *name){ - if (close(fd)){ - printout(LOG_INFO,"Device: %s, %s, close(%d) failed\n", name, strerror(errno), fd); - return 1; - } - // device sucessfully closed - return 0; -} - -// returns <0 on failure -int ataerrorcount(int fd, char *name){ - struct ata_smart_errorlog log; - - if (-1==ataReadErrorLog(fd,&log)){ - printout(LOG_INFO,"Device: %s, Read SMART Error Log Failed\n",name); - return -1; - } - - // return current number of ATA errors - return log.error_log_pointer?log.ata_error_count:0; -} - -// returns <0 if problem -int selftesterrorcount(int fd, char *name){ - struct ata_smart_selftestlog log; - - if (-1==ataReadSelfTestLog(fd,&log)){ - printout(LOG_INFO,"Device: %s, Read SMART Self Test Log Failed\n",name); - return -1; - } - - // return current number of self-test errors - return ataPrintSmartSelfTestlog(&log,0); -} - - - -// scan to see what ata devices there are, and if they support SMART -int atadevicescan2(atadevices_t *devices, cfgfile *cfg){ - int fd; - struct hd_driveid drive; - char *device=cfg->name; - - // should we try to register this as an ATA device? - if (!(cfg->tryata)) - return 1; - - // open the device - if ((fd=opendevice(device, O_RDONLY | O_NONBLOCK))<0) - // device open failed - return 1; - printout(LOG_INFO,"Device: %s, opened\n", device); - - // Get drive identity structure - if (ataReadHDIdentity (fd,&drive)){ - // Unable to read Identity structure - printout(LOG_INFO,"Device: %s, unable to read Device Identity Structure\n",device); - close(fd); - return 2; - } - - // pass user setings on to low-level ATA commands - con->fixfirmwarebug = cfg->fixfirmwarebug; - - // Show if device in database, and use preset vendor attribute - // options unless user has requested otherwise. - if (!cfg->ignorepresets){ - - // do whatever applypresets decides to do - if (applypresets(&drive, cfg->attributedefs, con)<0) - printout(LOG_INFO, "Device: %s, not found in smartd database.\n", device); - else - printout(LOG_INFO, "Device: %s, found in smartd database.\n", device); - - // then save the correct state of the flag (applypresets may have changed it) - cfg->fixfirmwarebug = con->fixfirmwarebug; - } - else - printout(LOG_INFO, "Device: %s, smartd database not searched (Directive: -P ignore).\n", device); - - // If requested, show which presets would be used for this drive - if (cfg->showpresets) { - int savedebugmode=debugmode; - printout(LOG_INFO, "Device %s: presets are:\n", device); - if (!debugmode) - debugmode=2; - showpresets(&drive); - debugmode=savedebugmode; - } - - if (!cfg->permissive && !ataSmartSupport(&drive)){ - // SMART not supported - printout(LOG_INFO,"Device: %s, appears to lack SMART, use '-T permissive' Directive to try anyway.\n",device); - close(fd); - return 2; - } - - if (ataEnableSmart(fd)){ - // Enable SMART command has failed - printout(LOG_INFO,"Device: %s, could not enable SMART capability\n",device); - close(fd); - return 2; - } - - // disable device attribute autosave... - if (cfg->autosave==1){ - if (ataDisableAutoSave(fd)) - printout(LOG_INFO,"Device: %s, could not disable SMART Attribute Autosave.\n",device); - else - printout(LOG_INFO,"Device: %s, disabled SMART Attribute Autosave.\n",device); - } - - // or enable device attribute autosave - if (cfg->autosave==2){ - if (ataEnableAutoSave(fd)) - printout(LOG_INFO,"Device: %s, could not enable SMART Attribute Autosave.\n",device); - else - printout(LOG_INFO,"Device: %s, enabled SMART Attribute Autosave.\n",device); - } - - // capability check: SMART status - if (cfg->smartcheck && ataSmartStatus2(fd)==-1){ - printout(LOG_INFO,"Device: %s, not capable of SMART Health Status check\n",device); - cfg->smartcheck=0; - } - - // capability check: Read smart values and thresholds - if (cfg->usagefailed || cfg->prefail || cfg->usage || cfg->autoofflinetest) { - devices->smartval=(struct ata_smart_values *)calloc(1,sizeof(struct ata_smart_values)); - devices->smartthres=(struct ata_smart_thresholds *)calloc(1,sizeof(struct ata_smart_thresholds)); - - if (!devices->smartval || !devices->smartthres){ - printout(LOG_CRIT,"Not enough memory to obtain SMART data\n"); - exit(EXIT_NOMEM); - } - - if (ataReadSmartValues(fd,devices->smartval) || - ataReadSmartThresholds (fd,devices->smartthres)){ - printout(LOG_INFO,"Device: %s, Read SMART Values and/or Thresholds Failed\n",device); - free(devices->smartval); - free(devices->smartthres); - - // make it easy to recognize that we've deallocated - devices->smartval=NULL; - devices->smartthres=NULL; - cfg->usagefailed=cfg->prefail=cfg->usage=0; - } - } - - // disable automatic on-line testing - if (cfg->autoofflinetest==1){ - if (devices->smartval && isSupportAutomaticTimer(devices->smartval) && !ataDisableAutoOffline(fd)) - printout(LOG_INFO,"Device: %s, disabled SMART Automatic Offline Testing .\n",device); - else - printout(LOG_INFO,"Device: %s, could not disable SMART Automatic Offline Testing.\n",device); - } - - // enable automatic on-line testing - if (cfg->autoofflinetest==2){ - if (devices->smartval && isSupportAutomaticTimer(devices->smartval) && !ataDisableAutoOffline(fd)) - printout(LOG_INFO,"Device: %s, enabled SMART Automatic Offline Testing.\n",device); - else - printout(LOG_INFO,"Device: %s, could not enable SMART Automatic Offline Testing.\n",device); - } - - // capability check: self-test-log - if (cfg->selftest){ - int val; - - // see if device supports Self-test logging. Note that the - // following line is not a typo: Device supports self-test log if - // and only if it also supports error log. - if (!isSmartErrorLogCapable(devices->smartval)){ - printout(LOG_INFO, "Device: %s, does not support SMART Self-test Log.\n", device); - cfg->selftest=0; - cfg->selflogcount=0; - } - else { - // get number of Self-test errors logged - val=selftesterrorcount(fd, device); - if (val>=0) - cfg->selflogcount=val; - else - cfg->selftest=0; - } - } - - // capability check: ATA error log - if (cfg->errorlog){ - int val; - - // see if device supports error logging - if (!isSmartErrorLogCapable(devices->smartval)){ - printout(LOG_INFO, "Device: %s, does not support SMART Error Log.\n", device); - cfg->errorlog=0; - cfg->ataerrorcount=0; - } - else { - // get number of ATA errors logged - val=ataerrorcount(fd, device); - if (val>=0) - cfg->ataerrorcount=val; - else - cfg->errorlog=0; - } - } - - // If no tests available or selected, return - if (!(cfg->errorlog || cfg->selftest || cfg->smartcheck || - cfg->usagefailed || cfg->prefail || cfg->usage)) { - close(fd); - return 3; - } - - // Do we still have entries available? - if (numatadevices>=MAXATADEVICES){ - printout(LOG_CRIT,"smartd has found more than MAXATADEVICES=%d ATA devices.\n" - "Recompile code from " PROJECTHOME " with larger MAXATADEVICES\n",(int)numatadevices); - exit(EXIT_CCONST); - } - - // register device - printout(LOG_INFO,"Device: %s, is SMART capable. Adding to \"monitor\" list.\n",device); - - // we were called from a routine that has global storage for the name. Keep pointer. - devices->devicename=device; - devices->cfg=cfg; - - // record number of device, type of device, increment device count - cfg->tryscsi=0; - cfg->tryata=1; - cfg->atadevicenum=numatadevices; - cfg->scsidevicenum=-1; - numatadevices++; - - // close file descriptor - closedevice(fd, device); - return 0; -} - - -static int scsidevicescan(scsidevices_t *devices, cfgfile *cfg, - int scandirective) -{ - int k, fd, err; - char *device = cfg->name; - struct scsi_iec_mode_page iec; - UINT8 tBuf[64]; - - // should we try to register this as a SCSI device? - if (! cfg->tryscsi) - return 1; - // open the device - if ((fd = opendevice(device, O_RDWR | O_NONBLOCK)) < 0) { - if (scandirective) - return 1; - printout(LOG_WARNING, "Device: %s, skip\n", device); - return 0; // device open failed - } - printout(LOG_INFO,"Device: %s, opened\n", device); - - // check that it's ready for commands. IE stores its stuff on the media. - if ((err = scsiTestUnitReady(fd))) { - if (1 == err) { - printout(LOG_WARNING, "Device: %s, NOT READY (media absent, spun " - "down); skip\n", device); - close(fd); - return scandirective ? 1 : 0; - } else { - printout(LOG_ERR, "Device: %s, failed Test Unit Ready [err=%d]\n", - device, err); - close(fd); - return 2; - } - } - - if ((err = scsiFetchIECmpage(fd, &iec))) { - printout(LOG_WARNING, "Device: %s, Fetch of IEC (SMART) mode page " - "failed, err=%d, skip device\n", device, err); - return 0; - } - if (! scsi_IsExceptionControlEnabled(&iec)) { - printout(LOG_WARNING, "Device: %s, IE (SMART) not enabled, " - "skip device\n", device); - close(fd); - return 0; - } - - // Device exists, and does SMART. Add to list - if (numscsidevices >= MAXSCSIDEVICES) { - printout(LOG_ERR, "smartd has found more than MAXSCSIDEVICES=%d " - "SCSI devices.\n" "Recompile code from " PROJECTHOME - " with larger MAXSCSIDEVICES\n", (int)numscsidevices); - return 0; - } - - // now we can proceed to register the device - printout(LOG_INFO, "Device: %s, is SMART capable. Adding " - "to \"monitor\" list.\n",device); - - // since device points to global memory, just keep that address - devices->devicename = device; - devices->cfg = cfg; - - // Flag that certain log pages are supported (information may be - // available from other sources). - if (0 == scsiLogSense(fd, SUPPORTED_LOG_PAGES, tBuf, sizeof(tBuf))) { - for (k = 4; k < tBuf[3] + LOGPAGEHDRSIZE; ++k) { - switch (tBuf[k]) { - case TEMPERATURE_PAGE: - devices->TempPageSupported = 1; - break; - case IE_LOG_PAGE: - devices->SmartPageSupported = 1; - break; - default: - break; - } - } - } - - // record number of device, type of device, increment device count - cfg->tryata = 0; - cfg->tryscsi = 1; - cfg->scsidevicenum = numscsidevices; - cfg->atadevicenum = -1; - ++numscsidevices; - - // close file descriptor - closedevice(fd, device); - return 0; -} - -// 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. -int ataCompareSmartValues(changedattribute_t *delta, - struct ata_smart_values *new, - struct ata_smart_values *old, - struct ata_smart_thresholds *thresholds, - int n, 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 || !new || !old || !thresholds) - return 0; - - // pointers to disk's values and vendor's thresholds - now=new->vendor_attributes+n; - was=old->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=now->status.flag.prefailure; - delta->sameraw=sameraw; - - return 1; -} - -// This looks to see if the corresponding bit of the 32 bytes is set. -// This wastes a few bytes of storage but eliminates all searching and -// sorting functions! Entry is ZERO <==> the attribute ON. Calling -// with set=0 tells you if the attribute is being tracked or not. -// Calling with set=1 turns the attribute OFF. -int isattoff(unsigned char attr,unsigned char *data, int set){ - // locate correct attribute - int loc=attr>>3; - int bit=attr & 0x07; - unsigned char mask=0x01<<bit; - - // attribute zero is always OFF - if (!attr) - return 1; - - if (!set) - return (data[loc] & mask); - - data[loc]|=mask; - // return value when setting makes no sense! - return 0; -} - - -int ataCheckDevice(atadevices_t *drive){ - int fd,i; - char *name=drive->devicename; - cfgfile *cfg=drive->cfg; - - // fix firmware bug if requested - con->fixfirmwarebug=cfg->fixfirmwarebug; - - // If user has asked, test the email warning system - if (cfg->emailtest){ - printandmail(cfg, 0, LOG_CRIT, "TEST EMAIL from smartd for device: %s", drive->devicename); - } - - // if we can't open device, fail gracefully rather than hard -- - // perhaps the next time around we'll be able to open it. ATAPI - // cd/dvd devices will hang awaiting media if O_NONBLOCK is not - // given (see linux cdrom driver). - if ((fd=opendevice(name, O_RDONLY | O_NONBLOCK))<0){ - printandmail(cfg, 9, LOG_CRIT, "Device: %s, unable to open device", name); - return 1; - } - - // check smart status - if (cfg->smartcheck){ - int status=ataSmartStatus2(fd); - if (status==-1){ - printout(LOG_INFO,"Device: %s, not capable of SMART self-check\n",name); - printandmail(cfg, 5, LOG_CRIT, "Device: %s, not capable of SMART self-check", name); - } - else if (status==1){ - printout(LOG_CRIT, "Device: %s, FAILED SMART self-check. BACK UP DATA NOW!\n", name); - printandmail(cfg, 1, LOG_CRIT, "Device: %s, FAILED SMART self-check. BACK UP DATA NOW!", name); - } - } - - // Check everything that depends upon SMART Data (eg, Attribute values) - if (cfg->usagefailed || cfg->prefail || cfg->usage){ - struct ata_smart_values curval; - struct ata_smart_thresholds *thresh=drive->smartthres; - - // Read current attribute values. *drive contains old values and thresholds - if (ataReadSmartValues(fd,&curval)){ - printout(LOG_CRIT, "Device: %s, failed to read SMART Attribute Data\n", name); - printandmail(cfg, 6, LOG_CRIT, "Device: %s, failed to read SMART Attribute Data", name); - } - else { - // look for failed usage attributes, or track usage or prefail attributes - for (i=0; i<NUMBER_ATA_SMART_ATTRIBUTES; i++){ - int att; - changedattribute_t delta; - - - // 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. - if (cfg->usagefailed && ((att=ataCheckAttribute(&curval, thresh, i))<0)){ - - // are we ignoring failures of this attribute? - att *= -1; - if (!isattoff(att, cfg->monitorattflags, 0)){ - char attname[64], *loc=attname; - - // get attribute name & skip white space - ataPrintSmartAttribName(loc, att, cfg->attributedefs[att]); - while (*loc && *loc==' ') loc++; - - // warning message - printout(LOG_CRIT, "Device: %s, Failed SMART usage Attribute: %s.\n", name, loc); - printandmail(cfg, 2, LOG_CRIT, "Device: %s, Failed SMART usage Attribute: %s.", name, loc); - } - } - - // 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. - if ((cfg->usage || cfg->prefail) && ataCompareSmartValues(&delta, &curval, drive->smartval, thresh, i, name)){ - unsigned char id=delta.id; - - // 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 && !isattoff(id, cfg->monitorattflags+96, 0)) - continue; - - // are we tracking this attribute? - if (!isattoff(id, cfg->monitorattflags+32, 0)){ - char newrawstring[64], oldrawstring[64], attname[64], *loc=attname; - - // get attribute name, skip spaces - ataPrintSmartAttribName(loc, id, cfg->attributedefs[id]); - while (*loc && *loc==' ') loc++; - - // has the user asked for us to print raw values? - if (isattoff(id, cfg->monitorattflags+64, 0)) { - // 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, drive->smartval->vendor_attributes+i, cfg->attributedefs); - sprintf(oldrawstring, " [Raw %s]", rawstring); - } - else - newrawstring[0]=oldrawstring[0]='\0'; - - // prefailure attribute - if (cfg->prefail && delta.prefail) - printout(LOG_INFO, "Device: %s, SMART Prefailure Attribute: %s changed from %d%s to %d%s\n", - name, loc, delta.oldval, oldrawstring, delta.newval, newrawstring); - - // usage attribute - if (cfg->usage && !delta.prefail) - printout(LOG_INFO, "Device: %s, SMART Usage Attribute: %s changed from %d%s to %d%s\n", - name, loc, delta.oldval, oldrawstring, delta.newval, newrawstring); - } - } // endof block tracking usage or prefailure - } // end of loop over attributes - - // Save the new values into *drive for the next time around - *drive->smartval=curval; - } - } - - // check if number of selftest errors has increased (note: may also DECREASE) - if (cfg->selftest){ - int new; - unsigned char old=cfg->selflogcount; - - // new self test error count - new=selftesterrorcount(fd, name); - - // did command fail? - if (new<0) - printandmail(cfg, 8, LOG_CRIT, "Device: %s, Read SMART Self Test Log Failed", name); - - // hsa self-test error count increased? - if (new>old){ - printout(LOG_CRIT, "Device: %s, Self-Test Log error count increased from %d to %d\n", - name, (int)old, new); - printandmail(cfg, 3, LOG_CRIT, "Device: %s, Self-Test Log error count increased from %d to %d", - name, (int)old, new); - } - - // Needed since self-test error count may DECREASE - if (new>=0) - cfg->selflogcount=new; - } - - - // check if number of ATA errors has increased - if (cfg->errorlog){ - - int new,old=cfg->ataerrorcount; - - // new number of errors - new=ataerrorcount(fd, name); - - // did command fail? - if (new<0) - printandmail(cfg, 7, LOG_CRIT, "Device: %s, Read SMART Error Log Failed", name); - - // has error count increased? - if (new>old){ - printout(LOG_CRIT, "Device: %s, ATA error count increased from %d to %d\n", - name, old, new); - printandmail(cfg, 4, LOG_CRIT, "Device: %s, ATA error count increased from %d to %d", - name, old, new); - } - - // this last line is probably not needed, count always increases - if (new>=0) - cfg->ataerrorcount=new; - } - - // Don't leave device open -- the OS/user may want to access it - // before the next smartd cycle! - closedevice(fd, name); - return 0; -} - - -int scsiCheckDevice(scsidevices_t *drive) -{ - UINT8 asc, ascq; - UINT8 currenttemp; - int fd; - cfgfile *cfg=drive->cfg; - char *name=drive->devicename; - const char *cp; - - // If the user has asked for it, test the email warning system - if (cfg->emailtest) - printandmail(cfg, 0, LOG_CRIT, - "TEST EMAIL from smartd for device: %s", name); - - // if we can't open device, fail gracefully rather than hard -- - // perhaps the next time around we'll be able to open it - if ((fd=opendevice(name, O_RDWR | O_NONBLOCK))<0) { - printandmail(cfg, 9, LOG_CRIT, "Device: %s, unable to open device", - name); - return 1; - } - currenttemp = 0; - asc = 0; - ascq = 0; - if (scsiCheckIE(fd, drive->SmartPageSupported, drive->TempPageSupported, - &asc, &ascq, ¤ttemp)) { - printout(LOG_INFO, "Device: %s, failed to read SMART values\n", name); - printandmail(cfg, 6, LOG_CRIT, - "Device: %s, failed to read SMART values", name); - } - if (asc > 0) { - cp = scsiGetIEString(asc, ascq); - if (cp) { - printout(LOG_CRIT, "Device: %s, SMART Failure: %s\n", name, cp); - printandmail(cfg, 1, LOG_CRIT, "Device: %s, SMART Failure: %s", - name, cp); - } - } else if (debugmode) - printout(LOG_INFO,"Device: %s, Acceptable asc,ascq: %d,%d\n", - name, (int)asc, (int)ascq); - - // Seems to completely ignore what capabilities were found on the - // device when scanned - if (currenttemp) { - if (255 == currenttemp) /* this means temperature unavailable */ - currenttemp = 0; /* less likely to worry people */ - if ((currenttemp != drive->Temperature) && (drive->Temperature)) - printout(LOG_INFO, "Device: %s, Temperature changed %d degrees " - "to %d degrees since last reading\n", name, - (int)(currenttemp - drive->Temperature), - (int)currenttemp); - drive->Temperature = currenttemp; - } - closedevice(fd, name); - return 0; -} - -void CheckDevices(atadevices_t *atadevices, scsidevices_t *scsidevices){ - static int firstpass=1; - int i; - - // Infinite loop, which checks devices - printout(LOG_INFO,"Started monitoring %d ATA and %d SCSI devices\n",numatadevices,numscsidevices); - while (1){ - for (i=0; i<numatadevices; i++) - ataCheckDevice(atadevices+i); - - for (i=0; i<numscsidevices; i++) - scsiCheckDevice(scsidevices+i); - - // This option is primarily for distribution developers who want - // an automated procedure for seeing if smartd works correctly. - // Use the -c/--checkonce option and verify zero exit status. - if (checkonce) { - printout(LOG_INFO,"Started with '-c' option. All devices sucessfully checked once.\n"); - exit(0); - } - - // Initialization setup - if (firstpass){ - - // If in background as a daemon, fork and close file descriptors - if (!debugmode) - daemon_init(); - - // install goobye message and remove pidfile handler - atexit(goodbye); - - // write PID file only after installing exit handler - if (!debugmode) - write_pid_file(); - - // install signal handlers - if (signal(SIGINT, sighandler)==SIG_IGN) - signal(SIGINT, SIG_IGN); - if (signal(SIGTERM, sighandler)==SIG_IGN) - signal(SIGTERM, SIG_IGN); - if (signal(SIGQUIT, sighandler)==SIG_IGN) - signal(SIGQUIT, SIG_IGN); - if (signal(SIGHUP, huphandler)==SIG_IGN) - signal(SIGHUP, SIG_IGN); - if (signal(SIGUSR1, sleephandler)==SIG_IGN) - signal(SIGUSR1, SIG_IGN); - - // done with initialization setup - firstpass=0; - } - - // Unix Gurus: I know that this can be done better. Please tell - // me how -- use email address for Bruce Allen at the top of this - // file. Search for "sleeptime" to see what I am doing. I think - // that when done "right" I should not have to call sleep once per - // second, but just set an alarm for checktime in the future, and - // then have an additional alarm sent if the user does SIGUSR1, - // which arrives first to cause another device check. Please help - // me out. - - // Sleep until next check. Note that since sleeptime can be set to - // zero by an EXTERNAL signal SIGUSR1, it's possible for sleeptime - // to be negative. Don't use while (sleeptime)! - sleeptime=checktime; - while (sleeptime-->0) - sleep(1); - } -} - -// Print out a list of valid arguments for the Directive d -void printoutvaliddirectiveargs(int priority, char d) { - char *s; - - switch (d) { - case 'd': - printout(priority, "ata, scsi"); - break; - case 'T': - printout(priority, "normal, permissive"); - break; - case 'o': - case 'S': - printout(priority, "on, off"); - break; - case 'l': - printout(priority, "error, selftest"); - break; - case 'M': - printout(priority, "\"once\", \"daily\", \"diminishing\", \"test\", \"exec\""); - break; - case 'v': - if (!(s = create_vendor_attribute_arg_list())) { - printout(LOG_CRIT,"Insufficient memory to construct argument list\n"); - break; - } - printout(priority, "\n%s\n", s); - free(s); - break; - case 'P': - printout(priority, "use, ignore, show, showall"); - break; - case 'F': - printout(priority, "none, samsung"); - break; - } -} - -char copyleftstring[]= -"smartd comes with ABSOLUTELY NO WARRANTY. This\n" -"is free software, and you are welcome to redistribute it\n" -"under the terms of the GNU General Public License Version 2.\n" -"See http://www.gnu.org for further details.\n\n"; - -cfgfile config[MAXENTRIES]; - -// exits with an error message, or returns integer value of token -int inttoken(char *arg, char *name, char *token, int lineno, char *configfile, int min, int max){ - char *endptr; - int val; - - // make sure argument is there - if (!arg) { - printout(LOG_CRIT,"File %s line %d (drive %s): Directive: %s takes integer argument from %d to %d.\n", - configfile, lineno, name, token, min, max); - Directives(); - exit(EXIT_BADCONF); - } - - // get argument value (base 10), check that it's integer, and in-range - val=strtol(arg,&endptr,10); - if (*endptr!='\0' || val<min || val>max ) { - printout(LOG_CRIT,"File %s line %d (drive %s): Directive: %s has argument: %s; needs integer from %d to %d.\n", - configfile, lineno, name, token, arg, min, max); - Directives(); - exit(EXIT_BADCONF); - } - - // all is well; return value - return val; -} - -// This function returns non-zero if it has correctly parsed a token, -// else zero if it has failed to parse a token. Or it exits with a -// Directive message if there is a token-parsing problem. -int parsetoken(char *token,cfgfile *cfg){ - char sym; - char *name=cfg->name; - int lineno=cfg->lineno; - char *delim = " \n\t"; - int badarg = 0; - int missingarg = 0; - char *arg = NULL; - - // is the rest of the line a comment - if (*token=='#') - return 1; - - // is the token not recognized? - if (*token!='-' || strlen(token)!=2) { - printout(LOG_CRIT,"File %s line %d (drive %s): unknown Directive: %s\n", - CONFIGFILE, lineno, name, token); - Directives(); - exit(EXIT_BADCONF); - } - - // let's parse the token and swallow its argument - switch (sym=token[1]) { - int val; - - case 'T': - // Set tolerance level for SMART command failures - if ((arg = strtok(NULL, delim)) == NULL) { - missingarg = 1; - } else if (!strcmp(arg, "normal")) { - // Normal mode: exit on failure of a mandatory S.M.A.R.T. command, but - // not on failure of an optional S.M.A.R.T. command. - // This is the default so we don't need to actually do anything here. - ; - } else if (!strcmp(arg, "permissive")) { - // Permissive mode; ignore errors from Mandatory SMART commands - cfg->permissive = 1; - } else { - badarg = 1; - } - break; - case 'd': - // specify the device type - if ((arg = strtok(NULL, delim)) == NULL) { - missingarg = 1; - } else if (!strcmp(arg, "ata")) { - cfg->tryata = 1; - cfg->tryscsi = 0; - } else if (!strcmp(arg, "scsi")) { - cfg->tryscsi = 1; - cfg->tryata = 0; - } else { - badarg = 1; - } - break; - case 'F': - // fix firmware bug - if ((arg = strtok(NULL, delim)) == NULL) { - missingarg = 1; - } else if (!strcmp(arg, "none")) { - cfg->fixfirmwarebug = FIX_NONE; - } else if (!strcmp(arg, "samsung")) { - cfg->fixfirmwarebug = FIX_SAMSUNG; - } else { - badarg = 1; - } - break; - case 'H': - // check SMART status - cfg->smartcheck=1; - break; - case 'f': - // check for failure of usage attributes - cfg->usagefailed=1; - break; - case 't': - // track changes in all vendor attributes - cfg->prefail=1; - cfg->usage=1; - break; - case 'p': - // track changes in prefail vendor attributes - cfg->prefail=1; - break; - case 'u': - // track changes in usage vendor attributes - cfg->usage=1; - break; - case 'l': - // track changes in SMART logs - if ((arg = strtok(NULL, delim)) == NULL) { - missingarg = 1; - } else if (!strcmp(arg, "selftest")) { - // track changes in self-test log - cfg->selftest=1; - } else if (!strcmp(arg, "error")) { - // track changes in ATA error log - cfg->errorlog=1; - } else { - badarg = 1; - } - break; - case 'a': - // monitor everything - cfg->smartcheck=1; - cfg->prefail=1; - cfg->usagefailed=1; - cfg->usage=1; - cfg->selftest=1; - cfg->errorlog=1; - break; - case 'o': - if ((arg = strtok(NULL, delim)) == NULL) { - missingarg = 1; - } else if (!strcmp(arg, "on")) { - cfg->autoofflinetest = 2; - } else if (!strcmp(arg, "off")) { - cfg->autoofflinetest = 1; - } else { - badarg = 1; - } - break; - case 'S': - if ((arg = strtok(NULL, delim)) == NULL) { - missingarg = 1; - } else if (!strcmp(arg, "on")) { - cfg->autosave = 2; - } else if (!strcmp(arg, "off")) { - cfg->autosave = 1; - } else { - badarg = 1; - } - break; - case 'M': - // email warning option - if ((arg = strtok(NULL, delim)) == NULL) { - missingarg = 1; - } else if (!strcmp(arg, "once")) { - cfg->emailfreq = 1; - } else if (!strcmp(arg, "daily")) { - cfg->emailfreq = 2; - } else if (!strcmp(arg, "diminishing")) { - cfg->emailfreq = 3; - } else if (!strcmp(arg, "test")) { - cfg->emailtest = 1; - } else if (!strcmp(arg, "exec")) { - // Get the next argument (the command line) - if ((arg = strtok(NULL, delim)) == NULL) { - printout(LOG_CRIT, "File %s line %d (drive %s): Directive %s 'exec' argument must be followed by executable path.\n", - CONFIGFILE, lineno, name, token); - Directives(); - exit(EXIT_BADCONF); - } - // Free the last cmd line given if any - if (cfg->emailcmdline) { - printout(LOG_INFO, "File %s line %d (drive %s): found multiple -M exec Directives on line - ignoring all but the last\n", CONFIGFILE, lineno, name); - free(cfg->emailcmdline); - } - // Attempt to copy the argument - if (!(cfg->emailcmdline = strdup(arg))) { - printout(LOG_CRIT, "File %s line %d (drive %s): no free memory for command line argument to exec: %s\n", - CONFIGFILE, lineno, name, arg); - Directives(); - exit(EXIT_NOMEM); - } - } else { - badarg = 1; - } - break; - case 'i': - // ignore failure of usage attribute - val=inttoken(arg=strtok(NULL,delim), name, token, lineno, CONFIGFILE, 1, 255); - isattoff(val,cfg->monitorattflags,1); - break; - case 'I': - // ignore attribute for tracking purposes - val=inttoken(arg=strtok(NULL,delim), name, token, lineno, CONFIGFILE, 1, 255); - isattoff(val,cfg->monitorattflags+32,1); - break; - case 'r': - // print raw value when tracking - val=inttoken(arg=strtok(NULL,delim), name, token, lineno, CONFIGFILE, 1, 255); - isattoff(val,cfg->monitorattflags+64,1); - break; - case 'R': - // track changes in raw value (forces printing of raw value) - val=inttoken(arg=strtok(NULL,delim), name, token, lineno, CONFIGFILE, 1, 255); - isattoff(val,cfg->monitorattflags+64,1); - isattoff(val,cfg->monitorattflags+96,1); - break; - case 'm': - // send email to address that follows - if ((arg = strtok(NULL,delim)) == NULL) { - printout(LOG_CRIT,"File %s line %d (drive %s): Directive: %s needs email address(es)\n", - CONFIGFILE, lineno, name, token); - Directives(); - exit(EXIT_BADCONF); - } - if (!(cfg->address=strdup(arg))){ - printout(LOG_CRIT,"File %s line %d (drive %s): Directive: %s: no free memory for email address(es) %s\n", - CONFIGFILE, lineno, name, token, arg); - Directives(); - exit(EXIT_NOMEM); - } - break; - case 'v': - // non-default vendor-specific attribute meaning - if ((arg=strtok(NULL,delim)) == NULL) { - missingarg = 1; - } else if (parse_attribute_def(arg, cfg->attributedefs)){ - badarg = 1; - } - break; - case 'P': - // Define use of drive-specific presets. - if ((arg = strtok(NULL, delim)) == NULL) { - missingarg = 1; - } else if (!strcmp(arg, "use")) { - cfg->ignorepresets = FALSE; - } else if (!strcmp(arg, "ignore")) { - cfg->ignorepresets = TRUE; - } else if (!strcmp(arg, "show")) { - cfg->showpresets = TRUE; - } else if (!strcmp(arg, "showall")) { - debugmode = TRUE; - showallpresets(); - exit(0); - } else { - badarg = 1; - } - break; - default: - // Directive not recognized - printout(LOG_CRIT,"File %s line %d (drive %s): unknown Directive: %s\n", - CONFIGFILE, lineno, name, token); - Directives(); - exit(EXIT_BADCONF); - } - if (missingarg) { - printout(LOG_CRIT, "File %s line %d (drive %s): Missing argument to Directive: %s\n", CONFIGFILE, lineno, name, token); - } - if (badarg) { - printout(LOG_CRIT, "File %s line %d (drive %s): Invalid argument: %s\n", CONFIGFILE, lineno, name, arg); - } - if (missingarg || badarg) { - printout(LOG_CRIT, "Valid arguments to %s Directive are: ", token); - printoutvaliddirectiveargs(LOG_CRIT, sym); - printout(LOG_CRIT, "\n"); - Directives(); - exit(EXIT_BADCONF); - } - return 1; -} - -int parseconfigline(int entry, int lineno,char *line){ - char *token,*copy; - char *name; - char *delim = " \n\t"; - cfgfile *cfg; - static int numtokens=0; - int devscan=0; - - if (!(copy=strdup(line))){ - printout(LOG_INFO,"No memory to parse file: %s line %d, %s\n", CONFIGFILE, lineno, strerror(errno)); - exit(EXIT_NOMEM); - } - - // get first token -- device name - if (!(name=strtok(copy,delim)) || *name=='#') { - free(copy); - return 0; - } - - // Have we detected the DEVICESCAN directive? - if (!strcmp(SCANDIRECTIVE,name)){ - devscan=1; - if (numtokens) { - printout(LOG_INFO,"Scan Directive %s must be the first entry in %s\n",name,CONFIGFILE); - exit(EXIT_BADCONF); - } - else - printout(LOG_INFO,"Scan Directive %s found in %s. Will scan for devices.\n",name,CONFIGFILE); - } - numtokens++; - - // Is there space for another entry? - if (entry>=MAXENTRIES){ - printout(LOG_CRIT,"Error: configuration file %s can have no more than MAXENTRIES=%d entries\n", - CONFIGFILE,MAXENTRIES); - exit(EXIT_CCONST); - } - - // We've got a legit entry, clear structure - cfg=config+entry; - memset(cfg,0,sizeof(*config)); - - // Save info to process memory for after forking 32 bytes contains 1 - // bit per possible attribute ID. See isattoff() - cfg->name=strdup(name); - if (!devscan){ - cfg->monitorattflags=(unsigned char *)calloc(NMONITOR*32,1); - cfg->attributedefs=(unsigned char *)calloc(256,1); - } - - // check that all memory allocations were sucessful - if (!cfg->name || (!devscan && (!cfg->monitorattflags || !cfg->attributedefs))) { - printout(LOG_INFO,"No memory to store file: %s line %d, %s\n", CONFIGFILE, lineno, strerror(errno)); - exit(EXIT_NOMEM); - } - - // Store line number, and by default check for both device types. - cfg->lineno=lineno; - cfg->tryscsi=1; - cfg->tryata=1; - - // Try and recognize if a IDE or SCSI device. These can be - // overwritten by configuration file directives. - if (GUESS_DEVTYPE_ATA == guess_linux_device_type(name)) - cfg->tryscsi=0; - else if (GUESS_DEVTYPE_SCSI == guess_linux_device_type(name)) - cfg->tryata=0; - /* in "don't know" case leave both tryata and tryscsi set */ - - // parse tokens one at a time from the file. This line actually - // parses ALL the tokens. - while ((token=strtok(NULL,delim)) && parsetoken(token,cfg)){ -#if 0 - printout(LOG_INFO,"Parsed token %s\n",token); -#endif - } - - // If no ATA monitoring directives are set, then set all of them. - if (cfg->tryata && !(cfg->smartcheck || cfg->usagefailed || cfg->prefail || - cfg->usage || cfg->selftest || cfg->errorlog)){ - - printout(LOG_INFO,"Drive: %s, implied '-a' Directive on line %d of file %s\n", - cfg->name, cfg->lineno, CONFIGFILE); - - cfg->smartcheck=1; - cfg->usagefailed=1; - cfg->prefail=1; - cfg->usage=1; - cfg->selftest=1; - cfg->errorlog=1; - } - - // additional sanity check. Has user set -M options without -m? - if (!cfg->address && (cfg->emailcmdline || cfg->emailfreq || cfg->emailtest)){ - printout(LOG_CRIT,"Drive: %s, -M Directive(s) on line %d of file %s need -m ADDRESS Directive\n", - cfg->name, cfg->lineno, CONFIGFILE); - Directives(); - exit(EXIT_BADCONF); - } - - // has the user has set <nomailer>? - if (cfg->address && !strcmp(cfg->address,"<nomailer>")){ - // check that -M exec is also set - if (!cfg->emailcmdline){ - printout(LOG_CRIT,"Drive: %s, -m <nomailer> Directive on line %d of file %s needs -M exec Directive\n", - cfg->name, cfg->lineno, CONFIGFILE); - Directives(); - exit(EXIT_BADCONF); - } - // now free memory. From here on the sign of <nomailer> is - // address==NULL and cfg->emailcmdline!=NULL - free(cfg->address); - cfg->address=NULL; - } - - // set cfg->emailfreq to 1 (once) if user hasn't set it - if (!cfg->emailfreq) - cfg->emailfreq = 1; - - entry++; - free(copy); - - // Return: - if (devscan) - return -1; - else - return 1; -} - -// returns number of entries in config file, or 0 if no config file -// exists. A config file with zero entries will cause an error -// message and an exit. Returns -1 if it found a SCANDEVICE directive -// in the config file. -int parseconfigfile(){ - FILE *fp; - int entry=0,lineno=1,cont=0,contlineno=0; - char line[MAXLINELEN+2]; - char fullline[MAXCONTLINE+1]; - - // Open config file, if it exists - fp=fopen(CONFIGFILE,"r"); - if (fp==NULL && errno!=ENOENT){ - // file exists but we can't read it - printout(LOG_CRIT,"%s: Unable to open configuration file %s\n", - strerror(errno),CONFIGFILE); - exit(EXIT_BADCONF); - } - - // No config file - if (fp==NULL) - return 0; - - // configuration file exists - printout(LOG_INFO,"Using configuration file %s\n",CONFIGFILE); - - // parse config file line by line - while (1) { - int len=0,scandevice; - char *lastslash; - char *comment; - char *code; - - // make debugging simpler - memset(line,0,sizeof(line)); - - // get a line - code=fgets(line,MAXLINELEN+2,fp); - - // are we at the end of the file? - if (!code){ - if (cont) { - scandevice=parseconfigline(entry,lineno,fullline); - // See if we found a SCANDEVICE directive - if (scandevice<0) - return -1; - // the final line is part of a continuation line - cont=0; - entry+=scandevice; - } - break; - } - - // input file line number - contlineno++; - - // See if line is too long - len=strlen(line); - if (len>MAXLINELEN){ - char *warn; - if (line[len-1]=='\n') - warn="(including newline!) "; - else - warn=""; - printout(LOG_CRIT,"Error: line %d of file %s %sis more than %d characters.\n", - (int)contlineno,CONFIGFILE,warn,(int)MAXLINELEN); - exit(EXIT_CCONST); - } - - // Ignore anything after comment symbol - if ((comment=index(line,'#'))){ - *comment='\0'; - len=strlen(line); - } - - // is the total line (made of all continuation lines) too long? - if (cont+len>MAXCONTLINE){ - printout(LOG_CRIT,"Error: continued line %d (actual line %d) of file %s is more than %d characters.\n", - lineno, (int)contlineno, CONFIGFILE, (int)MAXCONTLINE); - exit(EXIT_CCONST); - } - - // copy string so far into fullline, and increment length - strcpy(fullline+cont,line); - cont+=len; - - // is this a continuation line. If so, replace \ by space and look at next line - if ( (lastslash=rindex(line,'\\')) && !strtok(lastslash+1," \n\t")){ - *(fullline+(cont-len)+(lastslash-line))=' '; - continue; - } - - // Not a continuation line. Parse it - scandevice=parseconfigline(entry,lineno,fullline); - - // did we find a scandevice directive? - if (scandevice<0) - return -1; - - entry+=scandevice; - lineno++; - cont=0; - } - fclose(fp); - if (entry) - return entry; - - printout(LOG_CRIT,"Configuration file %s contains no devices (like /dev/hda)\n",CONFIGFILE); - exit(EXIT_BADCONF); -} - -// Prints copyright, license and version information -void PrintCopyleft(void){ - char out[CVSMAXLEN]; - debugmode=1; - printhead(); - printout(LOG_INFO,copyleftstring); - printout(LOG_INFO,"CVS version IDs of files used to build this code are:\n"); - printone(out,atacmds_c_cvsid); - printout(LOG_INFO,"%s",out); - printone(out,ataprint_c_cvsid); - printout(LOG_INFO,"%s",out); - printone(out,knowndrives_c_cvsid); - printout(LOG_INFO,"%s",out); - printone(out,scsicmds_c_cvsid); - printout(LOG_INFO,"%s",out); - printone(out,smartd_c_cvsid); - printout(LOG_INFO,"%s",out); - printone(out,utility_c_cvsid); - printout(LOG_INFO,"%s",out); - -} - -/* Returns a pointer to a static string containing a formatted list of the valid - arguments to the option opt or NULL on failure. */ -const char *getvalidarglist(char opt) { - switch (opt) { - case 'r': - return "ioctl[,N], ataioctl[,N], scsiioctl[,N]"; - case 'p': - return "<FILE_NAME>"; - case 'i': - return "<INTEGER_SECONDS>"; - default: - return NULL; - } -} - -/* Prints the message "=======> VALID ARGUMENTS ARE: <LIST> <=======\n", where - <LIST> is the list of valid arguments for option opt. */ -void printvalidarglistmessage(char opt) { - const char *s; - - printout(LOG_CRIT, "=======> VALID ARGUMENTS ARE: "); - if (!(s = getvalidarglist(opt))) - printout(LOG_CRIT, "Error constructing argument list for option %c", opt); - else - printout(LOG_CRIT, (char *)s); - printout(LOG_CRIT, " <=======\n"); -} - -// Parses input line, prints usage message and -// version/license/copyright messages -void ParseOpts(int argc, char **argv){ - extern char *optarg; - extern int optopt, optind, opterr; - int optchar; - int badarg; - char *tailptr; - long lchecktime; - // Please update getvalidarglist() if you edit shortopts - const char *shortopts = "cdDi:p:r:Vh?"; -#ifdef HAVE_GETOPT_LONG - char *arg; - // Please update getvalidarglist() if you edit longopts - struct option longopts[] = { - { "checkonce", no_argument, 0, 'c' }, - { "debug", no_argument, 0, 'd' }, - { "showdirectives", no_argument, 0, 'D' }, - { "interval", required_argument, 0, 'i' }, - { "pidfile", required_argument, 0, 'p' }, - { "report", required_argument, 0, 'r' }, - { "version", no_argument, 0, 'V' }, - { "license", no_argument, 0, 'V' }, - { "copyright", no_argument, 0, 'V' }, - { "help", no_argument, 0, 'h' }, - { "usage", no_argument, 0, 'h' }, - { 0, 0, 0, 0 } - }; -#endif - - opterr=optopt=0; - badarg=FALSE; - - // Parse input options: -#ifdef HAVE_GETOPT_LONG - while (-1 != (optchar = getopt_long(argc, argv, shortopts, longopts, NULL))){ -#else - while (-1 != (optchar = getopt(argc, argv, shortopts))){ -#endif - switch(optchar) { - case 'c': - checkonce = TRUE; - debugmode = TRUE; - break; - case 'd': - debugmode = TRUE; - break; - case 'D': - debugmode = TRUE; - Directives(); - exit(0); - break; - case 'i': - // Period (time interval) for checking - // strtol will set errno in the event of overflow, so we'll check it. - errno = 0; - lchecktime = strtol(optarg, &tailptr, 10); - if (*tailptr != '\0' || lchecktime < 10 || lchecktime > INT_MAX || errno) { - debugmode=1; - printhead(); - printout(LOG_CRIT, "======> INVALID INTERVAL: %s <=======\n", optarg); - printout(LOG_CRIT, "======> INTERVAL MUST BE INTEGER BETWEEN %d AND %d <=======\n", 10, INT_MAX); - printout(LOG_CRIT, "\nUse smartd -h to get a usage summary\n\n"); - exit(EXIT_BADCMD); - } - checktime = (int)lchecktime; - break; - case 'r': - { - int i; - char *s; - - // split_report_arg() may modify its first argument string, so use a - // copy of optarg in case we want optarg for an error message. - if (!(s = strdup(optarg))) { - printout(LOG_CRIT, "Can't allocate memory to copy argument to" - " -r option - exiting\n"); - exit(EXIT_NOMEM); - } - if (split_report_arg(s, &i)) { - badarg = TRUE; - } else if (!strcmp(s,"ioctl")) { - con->reportataioctl = con->reportscsiioctl = i; - } else if (!strcmp(s,"ataioctl")) { - con->reportataioctl = i; - } else if (!strcmp(s,"scsiioctl")) { - con->reportscsiioctl = i; - } else { - badarg = TRUE; - } - free(s); - } - break; - case 'p': - if( -1 == asprintf(&pid_file, "%s", optarg)) { - printout(LOG_CRIT, "Can't allocate memory for pid file name %s - exiting.\n", optarg); - pid_file = NULL; - exit(EXIT_NOMEM); - } - break; - case 'V': - PrintCopyleft(); - exit(0); - break; - case '?': - case 'h': - default: - debugmode=1; - printhead(); -#ifdef HAVE_GETOPT_LONG - // Point arg to the argument in which this option was found. - arg = argv[optind-1]; - // Check whether the option is a long option that doesn't map to -h. - if (arg[1] == '-' && optchar != 'h') { - // Iff optopt holds a valid option then argument must be missing. - if (optopt && (strchr(shortopts, optopt) != NULL)) { - printout(LOG_CRIT, "=======> ARGUMENT REQUIRED FOR OPTION: %s <=======\n",arg+2); - printvalidarglistmessage(optopt); - } else { - printout(LOG_CRIT, "=======> UNRECOGNIZED OPTION: %s <=======\n\n",arg+2); - } - printout(LOG_CRIT, "\nUse smartd --help to get a usage summary\n\n"); - exit(EXIT_BADCMD); - } -#endif - if (optopt) { - // Iff optopt holds a valid option then argument must be missing. - if (strchr(shortopts, optopt) != NULL){ - printout(LOG_CRIT, "=======> ARGUMENT REQUIRED FOR OPTION: %c <=======\n",optopt); - printvalidarglistmessage(optopt); - } else { - printout(LOG_CRIT, "=======> UNRECOGNIZED OPTION: %c <=======\n\n",optopt); - } - printout(LOG_CRIT, "\nUse smartd -h to get a usage summary\n\n"); - exit(EXIT_BADCMD); - } - Usage(); - exit(0); - } - - // Check to see if option had an unrecognized or incorrect argument. - if (badarg) { - debugmode=1; - printhead(); - // It would be nice to print the actual option name given by the user - // here, but we just print the short form. Please fix this if you know - // a clean way to do it. - printout(LOG_CRIT, "=======> INVALID ARGUMENT TO -%c: %s <======= \n", optchar, optarg); - printvalidarglistmessage(optchar); - printout(LOG_CRIT, "\nUse smartd -h to get a usage summary\n\n"); - exit(EXIT_BADCMD); - } - } - - // no pidfile in debug mode - if (debugmode && pid_file) { - printout(LOG_INFO, "warning: pid file %s not written in debug mode\n", pid_file); - free(pid_file); - pid_file = NULL; - } - - // print header - printhead(); - - return; -} - -// Function we call if no configuration file was found or if the -// DEVICESCAN Directive was found. It makes entries for /dev/hd[a-l] -// and /dev/sd[a-z]. -int makeconfigentries(int num, char *name, int isata, int start, int scandirective){ - int i; - - // check that we still have space for entries - if (MAXENTRIES<(start+num)){ - printout(LOG_CRIT,"Error: simulated config file can have no more than %d entries\n",(int)MAXENTRIES); - exit(EXIT_CCONST); - } - - // loop over the number of entries that we should create - for(i=0; i<num; i++){ - cfgfile *cfg=config+start+i; - - // If user has given the scan directive, copy config files entries - if (scandirective){ - memcpy(cfg, config, sizeof(*cfg)); - } - else { - // no config file was used: all structure entries need to be set - memset(cfg,0,sizeof(*cfg)); - - // enable all possible tests - cfg->smartcheck=1; - cfg->prefail=1; - cfg->usagefailed=1; - cfg->usage=1; - cfg->selftest=1; - cfg->errorlog=1; - - // lineno==0 is our clue that the device was not found in a - // config file! - cfg->lineno=0; - } - - // select if it's a SCSI or ATA device - cfg->tryata=isata; - cfg->tryscsi=!isata; - - // put in the device name - cfg->name=strdup(name); - cfg->monitorattflags=(unsigned char *)calloc(NMONITOR*32,1); - cfg->attributedefs=(unsigned char *)calloc(256,1); - if (!cfg->name || !cfg->monitorattflags || !cfg->attributedefs) { - printout(LOG_INFO,"No memory for %d'th device after %s, %s\n", i, name, strerror(errno)); - exit(EXIT_NOMEM); - } - - // increment final character of the name - cfg->name[strlen(name)-1]+=i; - } - return i; -} - -void cantregister(char *name, char *type, int line, int scandirective){ - if (line) - printout(scandirective?LOG_INFO:LOG_CRIT, - "Unable to register %s device %s at line %d of file %s\n", - type, name, line, CONFIGFILE); - else - printout(LOG_INFO,"Unable to register %s device %s\n", - type, name); - return; -} - - -/* Main Program */ -int main (int argc, char **argv){ - atadevices_t atadevices[MAXATADEVICES], *atadevicesptr=atadevices; - scsidevices_t scsidevices[MAXSCSIDEVICES], *scsidevicesptr=scsidevices; - int i, entries, scandirective=0, scanning=0; - smartmonctrl control; - - // initialize global communications variables - con=&control; - memset(con,0,sizeof(control)); - - // Parse input and print header and usage info if needed - ParseOpts(argc,argv); - - // Do we mute printing from ataprint commands? - con->quietmode=0; - con->veryquietmode=debugmode?0:1; - con->checksumfail=0; - - // look in configuration file CONFIGFILE (normally /etc/smartd.conf) - entries=parseconfigfile(); - - // if SCANDEVICE used or there was no /etc/smartd.conf config file, - // then create needed entries for scanning - if (entries<=0){ - int doscsi, doata; - - scanning=1; - - // Was SCANDEVICE Directive given? - scandirective=entries; - if (scandirective){ - printout(LOG_INFO,"smartd: Scanning for devices.\n"); - // free up storage used for SCANDIRECTIVE string - free(config->name); - config->name=NULL; - } - else { - // No config file given, so scan for both ATA and SCSI devices - printout(LOG_INFO,"smartd: file %s not found. Searching for ATA & SCSI devices.\n",CONFIGFILE); - config->tryata=1; - config->tryscsi=1; - } - - // initialize total number of entries to seach for - entries=0; - doata=config->tryata; - doscsi=config->tryscsi; - - // make list of ATA devices to search for - if (doata) - entries+=makeconfigentries(MAXATADEVICES, "/dev/hda", 1, entries, scandirective); - // make list of SCSI devices to search for - if (doscsi) - entries+=makeconfigentries(MAXSCSIDEVICES, "/dev/sda", 0, entries, scandirective); - } - - // Register entries - for (i=0;i<entries;i++){ - int notregistered=1; - - // register ATA devices - if (config[i].tryata){ - if (atadevicescan2(atadevicesptr+numatadevices, config+i)) - cantregister(config[i].name, "ATA", config[i].lineno, scandirective); - else - notregistered=0; - } - - // then register SCSI devices - if (config[i].tryscsi){ - if (scsidevicescan(scsidevicesptr+numscsidevices, config+i, - scandirective)) - cantregister(config[i].name, "SCSI", config[i].lineno, scandirective); - else - notregistered=0; - } - - // if device explictly listed and we can't register it, then exit - if (notregistered && !scanning){ - printout(LOG_CRIT, "Unable to register device %s - exiting.\n", config[i].name); - exit(EXIT_BADDEV); - } - } // done registering entries - - // If there are no devices to monitor, then exit - if (!numatadevices && !numscsidevices){ - printout(LOG_INFO,"Unable to monitor any SMART enabled ATA or SCSI devices.\n"); - exit(EXIT_BADDEV); - } - - // Now start an infinite loop that checks all devices - CheckDevices(atadevicesptr, scsidevicesptr); - return 0; -} - diff --git a/sm5/smartd.h b/sm5/smartd.h deleted file mode 100644 index 31d99d6df..000000000 --- a/sm5/smartd.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * smartd.h - * - * Home page of code is: http://smartmontools.sourceforge.net - * - * Copyright (C) 2002-3 Bruce Allen <smartmontools-support@lists.sourceforge.net> - * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org> - * - * 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 Software Foundation; either version 2, or (at your option) - * any later version. - * - * You should have received a copy of the GNU General Public License - * (for example COPYING); if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * This code was originally developed as a Senior Thesis by Michael Cornwell - * at the Concurrent Systems Laboratory (now part of the Storage Systems - * Research Center), Jack Baskin School of Engineering, University of - * California, Santa Cruz. http://ssrc.soe.ucsc.edu/ - * - */ - -#ifndef SMARTD_H_CVSID -#define SMARTD_H_CVSID "$Id: smartd.h,v 1.35 2003/04/19 09:53:42 pjwilliams Exp $\n" -#endif - -// Configuration file -#define CONFIGFILE "/etc/smartd.conf" - -// Scan directive for configuration file -#define SCANDIRECTIVE "DEVICESCAN" - -// maximum line length in configuration file -#define MAXLINELEN 128 - -// maximum number of device entries in configuration file. -#define MAXENTRIES 64 - -// maximum length of a continued line in configuration file -#define MAXCONTLINE 1023 - -// default for how often SMART status is checked, in seconds -#define CHECKTIME 1800 - -// maximum number of ATA devices to monitor -#define MAXATADEVICES 12 - -// maximum number of SCSI devices to monitor -#define MAXSCSIDEVICES 26 - -/* Boolean Values */ -#define TRUE 0x01 -#define FALSE 0x00 - -// Number of monitoring flags per Attribute. See monitorattflags -// below. -#define NMONITOR 4 - -// Exit codes -#define EXIT_BADCMD 1 // command line did not parse -#define EXIT_BADCONF 2 // problem reading/parsing config file -#define EXIT_STARTUP 3 // problem forking daemon -#define EXIT_PID 4 // problem creating pid file - -#define EXIT_NOMEM 8 // out of memory -#define EXIT_CCONST 9 // we hit a compile time constant - -#define EXIT_BADDEV 16 // we can't monitor this device -#define EXIT_NODEV 17 // no devices to monitor - -#define EXIT_SIGNAL 254 // abort on signal - -// If user has requested email warning messages, then this structure -// stores the information about them. -typedef struct mailinfo { - // number of times an email has been sent - int logged; - // time last email was sent, as defined by man 2 time - time_t lastsent; - // time problem initially logged - time_t firstsent; -} mailinfo; - -// Used to store a list of devices and options that were in the -// configuration file. -typedef struct configfile_s { - // Shich line was entry in file; what device type and name? - int lineno; - // Indicates corresponding entry number in the list of ata or scsi - // devices to monitor - int scsidevicenum; - int atadevicenum; - // Initially, tryata and tryscsi indicate which device to try. - // Ultimately, one is set and the other not set, depending upon - // which type of device was detected. - char tryata; - char tryscsi; - char *name; - // which tests have been enabled? - char smartcheck; - char usagefailed; - char prefail; - char usage; - char selftest; - char errorlog; - // Should we ignore missing capabilities/SMART errors - char permissive; - // Disable (1) or Enable (2) device attribute autosave - char autosave; - // Disable (1) or Enable (2) autmatic offline testing - char autoofflinetest; - // mailing information for four of the previous error types plus mailtest - mailinfo maildata[10]; - // Frequency with which to send emails: 1 - once, 2 - daily, 3 - diminishing - unsigned char emailfreq; - // Should we send a test email - unsigned char emailtest; - // Execute this command line and include output in emails - char *emailcmdline; - // address to send email to - char *address; - // counts of ata and self-test errors. Perhaps ought to be in the - // atadevices_t structure. - unsigned char selflogcount; - int ataerrorcount; - // following NMONITOR items each point to 32 bytes, in the form of - // 32x8=256 single bit flags - // valid attribute numbers are from 1 <= x <= 255 - // monitorattflags+0 set means ignore failure if it's a usage attribute - // monitorattflats+32 set means don't track attribute - // monitorattflags+64 set means print raw value when tracking - // monitorattflags+96 set means track changes in raw value - unsigned char *monitorattflags; - // See the end of extern.h for a definition of the array of 256 - // bytes that this points to. - unsigned char *attributedefs; - // enables equivalent of -F option for smartctl - unsigned char fixfirmwarebug; - // Don't use the preset vendor options from knowndrives[] for this device. - char ignorepresets; - // Show the preset vendor options from knowndrives[] for this device. - char showpresets; -} cfgfile; - - -// Used to store list of ATA devices to monitor. -typedef struct atadevices_s { - struct ata_smart_values *smartval; - struct ata_smart_thresholds *smartthres; - cfgfile *cfg; - char *devicename; -} atadevices_t; - -// used to store a list of SCSI devices to monitor. Devicename points -// to a malloced name string. -typedef struct scsidevices_s { - unsigned char SmartPageSupported; - unsigned char TempPageSupported; - unsigned char Temperature; - char *devicename; - cfgfile *cfg; -} scsidevices_t; - - -typedef struct changedattribute_s { - unsigned char newval; - unsigned char oldval; - unsigned char id; - unsigned char prefail; - unsigned char sameraw; -} changedattribute_t; - -// Declare our own printing functions... -void printout(int priority,char *fmt, ...) __attribute__ ((format(printf, 2, 3))); -void printandmail(cfgfile *cfg, int which, int priority, char *fmt, ...) __attribute__ ((format(printf, 4, 5))); - -int ataCheckDevice(atadevices_t *drive); diff --git a/sm5/smartd.initd b/sm5/smartd.initd deleted file mode 100755 index 973a98cfb..000000000 --- a/sm5/smartd.initd +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/bash -# chkconfig: 35 40 40 -# smartmontools init file for smartd -# -# description: Self Monitoring and Reporting Technology (SMART) Daemon -# -# processname: smartd -# -# $Id: smartd.initd,v 1.5 2003/03/06 07:27:18 ballen4705 Exp $ -# -# Copyright (C) 2002-3 Bruce Allen <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 the Free -# Software Foundation; either version 2, or (at your option) any later -# version. -# -# You should have received a copy of the GNU General Public License (for -# example COPYING); if not, write to the Free Software Foundation, Inc., 675 -# Mass Ave, Cambridge, MA 02139, USA. -# -# This code was originally developed as a Senior Thesis by Michael Cornwell -# at the Concurrent Systems Laboratory (now part of the Storage Systems -# Research Center), Jack Baskin School of Engineering, University of -# California, Santa Cruz. http://ssrc.soe.ucsc.edu/. -# -# source function library -. /etc/rc.d/init.d/functions - -case "$1" in - start) - echo -n "Starting smartd: " - daemon /usr/sbin/smartd - touch /var/lock/subsys/smartd - echo - ;; - stop) - echo -n "Shutting down smartd: " - killproc smartd - rm -f /var/lock/subsys/smartd - echo - ;; - restart) - $0 stop - $0 start - ;; - status) - status smartd - ;; - *) - echo "Usage: smartd {start|stop|restart|status}" - exit 1 -esac - -exit 0 diff --git a/sm5/smartmontools.spec b/sm5/smartmontools.spec deleted file mode 100644 index 5a4512dc5..000000000 --- a/sm5/smartmontools.spec +++ /dev/null @@ -1,727 +0,0 @@ -Release: 10 -Summary: SMARTmontools - for monitoring S.M.A.R.T. disks and devices -Summary(cs): SMARTmontools - pro monitorov�n� S.M.A.R.T. disk� a za��zen� -Summary(de): SMARTmontools - zur �berwachung von S.M.A.R.T.-Platten und-Ger�ten -Summary(es): SMARTmontools - para el seguimiento de discos y dispositivos S.M.A.R.T. -Summary(fr): SMARTmontools - pour le suivi des disques et instruments S.M.A.R.T. -Summary(pt): SMARTmontools - para monitorar discos e dispositivos S.M.A.R.T. -Summary(it): SMARTmontools - per monitare dischi e dispositivi S.M.A.R.T. -Summary(pl): Monitorowanie i kontrola dysk�w u�ywaj�� S.M.A.R.T. -Name: smartmontools -Version: 5.1 -License: GPL -Group: Applications/System -Group(de): Applikationen/System -Group(es): Aplicaciones/Sistema -Group(fr): Applications/Syst�me -Group(pt): Aplicativos/Sistema -Group(it): Applicazioni/Sistemi -Source0: %{name}-%{version}.tar.gz -URL: http://smartmontools.sourceforge.net/ -Prereq: /sbin/chkconfig -BuildRoot: %{_tmppath}/%{name}-%{version}-root -Obsoletes: smartctl -Obsoletes: smartd -Obsoletes: ucsc-smartsuite -Obsoletes: smartsuite -Packager: Bruce Allen <smartmontools-support@lists.sourceforge.net> - -# Source code can be found at: -# http://ftp1.sourceforge.net/smartmontools/smartmontools-%{version}-%{release}.tar.gz - -# CVS ID of this file is: -# $Id: smartmontools.spec,v 1.97 2003/04/23 13:19:40 guidog Exp $ - -# Copyright (C) 2002-3 Bruce Allen <smartmontools-support@lists.sourceforge.net> -# Home page: http://smartmontools.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 the Free -# Software Foundation; either version 2, or (at your option) any later -# version. -# -# You should have received a copy of the GNU General Public License (for -# example COPYING); if not, write to the Free Software Foundation, Inc., 675 -# Mass Ave, Cambridge, MA 02139, USA. -# -# This code was originally developed as a Senior Thesis by Michael Cornwell -# at the Concurrent Systems Laboratory (now part of the Storage Systems -# Research Center), Jack Baskin School of Engineering, University of -# California, Santa Cruz. http://ssrc.soe.ucsc.edu/ - - -%description -SMARTmontools controls and monitors storage devices using the -Self-Monitoring, Analysis and Reporting Technology System (S.M.A.R.T.) -built into ATA and SCSI Hard Drives. This is used to check the -reliability of the hard drive and to predict drive failures. The suite -is derived from the smartsuite package, and contains two utilities. The -first, smartctl, is a command line utility designed to perform simple -S.M.A.R.T. tasks. The second, smartd, is a daemon that periodically -monitors smart status and reports errors to syslog. The package is -compatible with the ATA/ATAPI-5 specification. Future releases will be -compatible with the ATA/ATAPI-6 andATA/ATAPI-7 specifications. The -package is intended to incorporate as much "vendor specific" and -"reserved" information as possible about disk drives. man smartctl and -man smartd will provide more information. This RPM file is compatible -with all RedHat releases back to at least 6.2 and should work OK on any -modern linux distribution. The most recent versions of this package and -additional information can be found at the URL: -http://smartmontools.sourceforge.net/ - -%description -l cs -SMARTmontools ��d� a monitoruj� za��zen� pro ukl�d�n� dat za pou�it� -technologie automatick�ho monitorov�n�, anal�zy a hl�en� -(Self-Monitoring, Analysis and Reporting Technology System - -S.M.A.R.T.) vestav�n�ho do pevn�ch disk� ATA a SCSI. Pou��v� se ke -kontrole pou�itelnosti pevn�ho disku a p�edv�d�n� hav�ri� disk�. -N�stroje jsou odvozeny od bal��ku smartsuite a obsahuj� dva programy. -Prvn�, smartctl, je n�stroj pro prov�d�n� jednoduch�ch S.M.A.R.T. �loh -na p��kazov� ��dce. Druh�, smartd, je d�mon, kter� periodicky -monitoruje stav a hl�s� chyby do syst�mov�ho protokolu. Bal��ek je -kompatibiln� se specifikac� ATA/ATAPI-5. Dal�� verze budou -kompatibiln� se specifikacemi ATA/ATAPI-6 a ATA/ATAPI-7. Bal��ek je -navr�en tak, aby pokryl co nejv�ce polo�ek s informacemi "z�visl� na -v�robci" a "rezervov�no". V�ce informac� z�sk�te pomoc� man smartctl a -man smartd. Tento RPM bal��ek je kompatibiln� se v�emi verzemi RedHatu -a m�l by fungovat na v�ech modern�ch distribuc�ch Linuxu. Aktu�ln� -verzi najdete na URL http://smartmontools.sourceforge.net/ - -%description -l de -Die SMARTmontools steuern und �berwachen Speicherger�te mittels des -S.M.A.R.T.-Systems (Self-Monitoring, Analysis and Reporting Technology, -Technologie zur Selbst-�berwachung, Analyse und Berichterstellung), das -in ATA- und SCSI-Festplatten eingesetzt wird. Sie werden benutzt, um -die Zuverl�ssigkeit der Festplatte zu pr�fen und Plattenfehler -vorherzusagen. Die Suite wurde vom smartsuite-Paket abgeleitet und -enth�lt zwei Dienstprogramme. Das erste, smartctl, ist ein -Kommandozeilentool, das einfache S.M.A.R.T. Aufgaben ausf�hrt. Das -zweite, smartd, ist ein Daemon, der periodisch den S.M.A.R.T.-Status -�berwacht und Fehler ins Syslog protokolliert. Das Paket ist zur -ATA/ATAPI-5 Spezifikation kompatibel. Zuk�nftige Versionen werden auch -die ATA/ATAPI-6 und ATA/ATAPI-7 Spezifikationen umsetzen. Das Paket -versucht, so viele "herstellerspezifische" und "reservierte" Information -�ber Plattenlaufwerke wie m�glich bereitzustellen. man smartctl und man -smartd liefern mehr Informationen �ber den Einsatz. Dieses RPM ist zu -allen RedHat-Versionen ab sp�testens 6.2 kompatibel und sollte unter -jedem modernen Linux arbeiten. Die aktuellsten Versionen dieses Pakets -und zus�tzliche Informationen sind zu finden unter der URL: -http://smartmontools.sourceforge.net/ - -%description -l es -SMARTmontools controla y hace el seguimiento de dispositivos de -almacenamiento usando el Self-Monitoring, Analysis and Reporting -Technology System (S.M.A.R.T.) incorporado en discos duros ATA y SCSI. -Es usado para asegurar la fiabilidad de discos duros y predecir averias. -El conjunto de programas proviene del conjunto smartsuite y contiene dos -utilidades. La primera, smartctl, es una utilidad command-line hecha -para hacer operaciones S.M.A.R.T. sencillas. La segunda, smartd, es un -programa que periodicamente chequea el estatus smart e informa de -errores a syslog. Estos programas son compatibles con el sistema -ATA/ATAPI-5. Futuras versiones seran compatibles con los sistemas -ATA/ATAPI-6 y ATA/ATAPI-7. Este conjunto de programas tiene el -proposito de incorporar la mayor cantidad posible de informacion -reservada y especifica de discos duros. Los comandos 'man smartctl' y -'man smartd' contienen mas informacion. Este fichero RPM es compatible -con todas las versiones de RedHat a partir de la 6.2 y posiblemente -funcionaran sin problemas en cualquier distribucion moderna de linux. -La version mas reciente de estos programas ademas de informacion -adicional pueden encontrarse en: http://smartmontools.sourceforge.net/ - -%description -l fr -SMARTmontools contr�le et fait le suivi de p�riph�riques de stockage -utilisant le syst�me Self-Monitoring, Analysis and Reporting -Technology (S.M.A.R.T) int�gr�dans les disques durs ATA et SCSI. Ce -syst�me est utilis� pour v�rifier la fiabilit� du disque dur et pr�dire -les d�faillances du lecteur. La suite logicielle d�rive du paquet -smartsuite et contient deux utilitaires. Le premier, smartctl, -fonctionne en ligne de commande et permet de r�aliser des t�ches -S.M.A.R.T. simples. Le second, smartd, est un d�mon qui fait -p�riodiquement le suivi du statut smart et transmet les erreurs au -syslog. Ce paquet est compatible avec la sp�cification ATA/ATAPI-5. -Les prochaines versions seront compatibles avec les sp�cifications -ATA/ATAPI-6 et ATA/ATAPI-7. Ce paquet tente d'incorporer le plus -d'informations possible sur les disques durs qu'elles soient sp�cifiques -au constructeur ("vendor specific") ou r�serv�es ("reserved"). man -smartctl et man smartd donnent plus de renseignements. Ce fichier RPM -est compatible avec toutes les versions de RedHat v6.2 et ult�rieures, -et devrait fonctionner sur toutes les distributions r�centes de Linux. -Les derni�res versions de ce paquet et des informations suppl�mentaires -peuvent �tre trouv�es � l'adresse URL: -http://smartmontools.sourceforge.net/ - -%description -l pt -SMARTmontools controla e monitora dispositivos de armazenamento -utilizando o recurso Self-Monitoring, Analysis and Reporting Technology -System (S.M.A.R.T.) integrado nos discos r�gidos ATA e SCSI, cuja -finalidade � verificar a confiabilidade do disco r�gido e prever falhas -da unidade. A suite � derivada do pacote smartsuite, e cont�m dois -utilit�rios. O primeiro, smartctl, � um utilit�rio de linha de comando -projetado para executar tarefas simples de S.M.A.R.T. O segundo, -smartd, � um daemon que monitora periodicamente estados do smart e -reporta erros para o syslog. O pacote � compat�vel com a especifica��o -ATA/ATAPI-5. Futuras vers�es ser�o compat�veis com as especifica��es -ATA/ATAPI-6 e ATA/ATAPI-7. O pacote pretende incorporar o maior n�mero -poss�vel de informa��es "espec�ficas do fabricante" e "reservadas" sobre -unidades de disco. man smartctl e man smartd cont�m mais informa��es. -Este arquivo RPM � compat�vel com todas as vers�es do RedHat a partir da -6.2 e dever� funcionar perfeitamente em qualquer distribui��o moderna do -Linux. As mais recentes vers�es deste pacote e informa��es adicionais -podem ser encontradas em http://smartmontools.sourceforge.net/ - -%description -l it -SMARTmontools controlla e monitora dischi che usano il "Self-Monitoring, -Analysis and Reporting Technology System" (S.M.A.R.T.), in hard drive -ATA e SCSI. Esso � usato per controllare l'affidabilit� dei drive e -predire i guasti. La suite � derivata dal package smartsuite e contiene -due utility. La prima, smartctl, � una utility a linea di comando -progettata per eseguire semplici task S.M.A.R.T.. La seconda, smartd, � -un daemon che periodicamente monitora lo stato di smart e riporta errori -al syslog. Il package � compatibile con le specifiche ATA/ATAPI-6 e -ATA/ATAPI-7. Il package vuole incorporare tutte le possibili -informazioni riservate e "vendor specific" sui dischi. man smartctl e -man smartd danno pi� informazioni. Questo file RPM � compatibile con -tutte le release di RedHat, almeno dalla 6.2 e dovrebbe funzionare bene -su ogni moderna distribuzione di linux. Le versioni pi� recenti di -questo package e informazioni addizionali possono essere trovate al sito -http://smartmontools.sourceforge.net/ - -%description -l pl -Pakiet zawiera dwa programy (smartctl oraz smartd) do kontroli i -monitorowania system�w przechowywania danych za pomoc� S.M.A.R.T - -systemu wbudowanego w wi�kszo�� nowych dysk�w ATA oraz SCSI. Pakiet -pochodzi od oprogramowania smartsuite i wspiera dyski ATA/ATAPI-5. - -# The following sections are executed by the SRPM file -%prep - -%setup -q - -%build -make - -%install -rm -rf $RPM_BUILD_ROOT -make DESTDIR=$RPM_BUILD_ROOT install - -%files -%defattr(-,root,root) -%attr(755,root,root) %{_sbindir}/smartd -%attr(755,root,root) %{_sbindir}/smartctl -%attr(755,root,root) /etc/rc.d/init.d/smartd -%attr(644,root,root) %{_mandir}/man8/smartctl.8* -%attr(644,root,root) %{_mandir}/man8/smartd.8* -%attr(644,root,root) %{_mandir}/man5/smartd.conf.5* -%doc WARNINGS CHANGELOG COPYING TODO README VERSION smartd.conf examplescripts -%config(noreplace) %{_sysconfdir}/smartd.conf - -%clean -rm -rf $RPM_BUILD_ROOT -rm -rf %{_builddir}/%{name}-%{version} - -# The following are executed only by the binary RPM at install/uninstall - -# since this installs the gzipped documentation files, remove -# non-gzipped ones of the same name. -%pre -if [ -f /usr/share/man/man8/smartctl.8 ] ; then - echo "You MUST delete (by hand) the outdated file /usr/share/man/man8/smartctl.8 to read the new manual page for smartctl." -fi -if [ -f /usr/share/man/man8/smartd.8 ] ; then - echo "You MUST delete (by hand) the outdated file /usr/share/man/man8/smartd.8 to read the new manual page for smartd." -fi - -%post -if [ -f /var/lock/subsys/smartd ]; then - /etc/rc.d/init.d/smartd restart 1>&2 - echo "Restarted smartd services" -else - echo "Run \"/etc/rc.d/init.d/smartd start\" to start smartd service now." - echo "Run \"/sbin/chkconfig --add smartd\", to start smartd service on system boot" -fi -echo "Note that you can now use a configuration file /etc/smartd.conf to control the" -echo "startup behavior of the smartd daemon. See man 8 smartd for details." - -%preun -if [ -f /var/lock/subsys/smartd ]; then - /etc/rc.d/init.d/smartd stop 1>&2 - echo "Stopping smartd services" -fi -/sbin/chkconfig --del smartd - -%define date %(echo `LC_ALL="C" date +"%a %b %d %Y"`) -%changelog -* Mon Apr 21 2003 Bruce Allen <smartmontools-support@lists.sourceforge.net> -- [PW] Extended the -F option/Directive to potentially fix other firmware - bugs in addition to the Samsung byte-order bug. Long option name is - now --firmwarebug and the option/Directive accepts an argument - indicating the type of firmware bug to fix. -- [BA] Fixed a bug that prevented the enable automatic off-line - test feature from enabling. It also prevented the enable Attribute - autosave from working. See CVS entry for additional details. -- [PW] Modified the -r/--report option (smartctl and smartd) to allow the - user to specify the debug level as a positive integer. -- [BA] Added --log directory option to smartctl. If the disk - supports the general-purpose logging feature set (ATA-6/7) - then this option enables the Log Directory to be printed. - This Log Directory shows which device logs are available, and - their lengths in sectors. -- [PW] Added -P/--presets option to smartctl and -P Directive to smartd. -- [GG] Introduce different exit codes indicating the type of problem - encountered for smartd. -- [DG] Add non-medium error count to '-l error' and extended self test - duration to '-l selftest'. Get scsi IEs and temperature changes - working in smartd. Step over various scsi disk problems rather - than abort smartd startup. -- [DG] Support -l error for SCSI disks (and tapes). Output error counter - log pages. -- [BA] Added -F/--fixbyteorder option to smartctl. This allows us to read - SMART data from some disks that have byte-reversed two- and four- - byte quantities in their SMART data structures. -- [BA] Fixed serious bug: the -v options in smartd.conf were all put - together and used together, not drive-by-drive. -- [PW] Added knowndrives.h and knowndrives.c. The knowndrives array - supersedes the drivewarnings array. -- [GG] add {-p,--pidfile} option to smartd to write a PID file on - startup. Update the manpage accordingly. -- [DG] Fix scsi smartd problem detecting SMART support. More cleaning - and fix (and rename) scsiTestUnitReady(). More scsi renaming. -- [BA] Fixed smartd so that if a disk that is explictily listed is not - found, then smartd will exit with nonzero status BEFORE forking. - If a disk can't be registered, this will also be detected before - forking, so that init scripts can react correctly. -- [BA] Replaced all linux-specific ioctl() calls in atacmds.c with - a generic handler smartcommandhandler(). Now the only routine - that needs to be implemented for a given OS is os_specific_handler(). - Also implemented the --report ataioctl. This provides - two levels of reporting. Using the option once gives a summary - report of device IOCTL transactions. Using the option twice give - additional info (a printout of ALL device raw 512 byte SMART - data structures). This is useful for debugging. -- [DG] more scsi cleanup. Output scsi device serial number (VPD page - 0x80) if available as part of '-i'. Implement '-t offline' as - default self test (only self test older disks support). -- [BA] Changed crit to info in loglevel of smartd complaint to syslog - if DEVICESCAN enabled and device not found. -- [BA] Added -v 194,10xCelsius option/Directive. Raw Attribute number - 194 is ten times the disk temperature in Celsius. -- [DG] scsicmds.[hc] + scsiprint.c: clean up indentation, remove tabs. - Introduce new intermediate interface based on "struct scsi_cmnd_io" - to isolate SCSI generic commands + responses from Linux details; - should help port to FreeBSD of SCSI part of smartmontools. - Make SCSI command builders more parametric. - -* Thu Mar 13 2003 Bruce Allen <smartmontools-support@lists.sourceforge.net> -- [BA] smartctl: if HDIO_DRIVE_TASK ioctl() is not implemented (no - kernel support) then try to assess drive health by examining - Attribute values/thresholds directly. -- [BA] smartd/smartctl: added -v 200,writeerrorcount option/Directive - for Fujitsu disks. -- [BA] smartd: Now send email if any of the SMART commands fails, - or if open()ing the device fails. This is often noted - as a common disk failure mode. -- [BA] smartd/smartctl: Added -v N,raw8 -v N,raw16 and -v N,raw48 - Directives/Options for printing Raw Attributes in different - Formats. -- [BA] smartd: Added -r ID and -R ID for reporting/tracking Raw - values of Attributes. -- [BA] smartd/smartctl: Changed printing of spin-up-time attribute - raw value to reflect current/average as per IBM standard. -- [BA] smartd/smartctl: Added -v 9,seconds option for disks which - use Attribute 9 for power-on lifetime in seconds. -- [BA] smartctl: Added a warning message so that users of some IBM - disks are warned to update their firmware. Note: we may want - to add a command-line flag to disable the warning messages. - I have done this in a general way, using regexp, so that we - can add warnings about any type of disk that we wish.. - -* Wed Feb 12 2003 Bruce Allen <smartmontools-support@lists.sourceforge.net> -- [BA] smartd: Created a subdirectory examplescripts/ of source - directory that contains executable scripts for the -M exec PATH - Directive of smartd. -- [BA] smartd: DEVICESCAN in /etc/smartd.conf - can now be followed by all the same Directives as a regular - device name like /dev/hda takes. This allows one to use - (for example): - DEVICESCAN -m root@yoyodyne.com - in the /etc/smartd.conf file. -- [BA] smartd: Added -c (--checkonce) command-line option. This checks - all devices once, then exits. The exit status can be - used to learn if devices were detected, and if smartd is - functioning correctly. This is primarily for Distribution - scripters. -- [BA] smartd: Implemented -M exec Directive for - smartd.conf. This makes it possible to run an - arbitrary script or mailing program with the - -m option. -- [PW] smartd: Modified -M Directive so that it can be given - multiple times. Added -M exec Directive. - -* Tue Jan 21 2003 Bruce Allen <smartmontools-support@lists.sourceforge.net> -- [BA] Fixed bug in smartctl pointed out by Pierre Gentile. - -d scsi didn't work because tryata and tryscsi were - reversed -- now works on /devfs SCSI devices. -- [BA] Fixed bug in smartctl pointed out by Gregory Goddard - <ggoddard@ufl.edu>. Manual says that bit 6 of return - value turned on if errors found in smart error log. But - this wasn't implemented. -- [BA] Modified printing format for 9,minutes to read - Xh+Ym not X h + Y m, so that fields are fixed width. -- [BA] Added Attribute 240 "head flying hours" - -* Sun Jan 12 2003 Bruce Allen <smartmontools-support@lists.sourceforge.net> -- [BA] As requested, local time/date now printed by smartctl -i - -* Thu Jan 9 2003 Bruce Allen <smartmontools-support@lists.sourceforge.net> -- [PW] Added 'help' argument to -v for smartctl -- [PW] Added -D, --showdirectives option to smartd - -* Sat Jan 4 2003 Bruce Allen <smartmontools-support@lists.sourceforge.net> -- [DG] add '-l selftest' capability for SCSI devices (update smartctl.8) -- [BA] smartd,smartctl: added additional Attribute modification option - -v 220,temp and -v 9,temp. -- [PW] Renamed smartd option -X to -d -- [PW] Changed smartd.conf Directives -- see man page -- [BA/DG] Fixed uncommented comment in smartd.conf -- [DG] Correct 'Recommended start stop count' for SCSI devices -- [PW] Replaced smartd.conf directive -C with smartd option -i -- [PW] Changed options for smartctl -- see man page. -- [BA] Use strerror() to generate system call error messages. -- [BA] smartd: fflush() all open streams before fork(). -- [BA] smartctl, smartd simplified internal handling of checksums - for simpler porting and less code. - -* Sun Dec 8 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net> -- [PW] smartd --debugmode changed to --debug -- [BA] smartd/smartctl added attribute 230 Head Amplitude from - IBM DPTA-353750. -- [PW] Added list of proposed new options for smartctl to README. -- [PW] smartd: ParseOpts() now uses getopt_long() if HAVE_GETOPT_LONG is - defined and uses getopt() otherwise. This is controlled by CPPFLAGS in - the Makefile. -- [BA] smartd: Fixed a couple of error messages done with perror() - to redirect them as needed. -- [BA] smartctl: The -O option to enable an Immediate off-line test - did not print out the correct time that the test would take to - complete. This is because the test timer is volatile and not - fixed. This has been fixed, and the smartctl.8 man page has been - updated to explain how to track the Immediate offline test as it - progresses, and to further emphasize the differences between the - off-line immediate test and the self-tests. -- [BA] smartd/smartctl: Added new attribute (200) Multi_Zone_Error_Rate -- [BA] smartctl: modified so that arguments could have either a single - - as in -ea or multiple ones as in -e -a. Improved warning message for - device not opened, and fixed error in redirection of error output of - HD identity command. -- [PW] smartd: added support for long options. All short options are still - supported; see manpage for available long options. -- [BA] smartctl. When raw Attribute value was 2^31 or larger, did - not print correctly. - -* Fri Nov 22 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net> -- Allen: smartd: added smartd.conf Directives -T and -s. The -T Directive - enables/disables Automatic Offline Testing. The -s Directive - enables/disables Attribute Autosave. Documentation and - example configuration file updated to agree. -- Allen: smartd: user can make smartd check the disks at any time - (ie, interrupt sleep) by sending signal SIGUSR1 to smartd. This - can be done for example with: - kill -USR1 <pid> - where <pid> is the process ID number of smartd. -- Bolso: scsi: don't trust the data we receive from the drive too - much. It very well might have errors (like zero response length). - Seen on Megaraid logical drive, and verified in the driver source. -- Allen: smartd: added Directive -m for sending test email and - for modifying email reminder behavior. Updated manual, and sample - configuration file to illustrate & explain this. -- Allen: smartd: increased size of a continued smartd.conf line to - 1023 characters. -- Allen: Simplified Directive parsers and improved warning/error - messages. - -* Sun Nov 17 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net> -- Fixed bug in smartd where testunitready logic inverted - prevented functioning on scsi devices. -- Added testunitnotready to smartctl for symmetry with smartd. -- Brabec: added Czech descriptions to .spec file -- Brabec: corrected comment in smartd.conf example -- Changed way that entries in the ATA error log are printed, - to make it clearer which is the most recent error and - which is the oldest one. -- Changed Temperature_Centigrade to Temperature_Celsius. - The term "Centigrade" ceased to exist in 1948. (c.f - http://www.bartleby.com/64/C004/016.html). - -* Wed Nov 13 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net> -- smartd SCSI devices: can now send warning email message on failure -- Added a new smartd configuration file Directive: -M ADDRESS. - This sends a single warning email to ADDRESS for failures or - errors detected with the -c, -L, -l, or -f Directives. - -* Mon Nov 11 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net> -- Modified perror() statements in atacmds.c so that printout for SMART - commands errors is properly suppressed or queued depending upon users - choices for error reporting modes. -- Added Italian descriptions to smartmontools.spec file. -- Started impementing send-mail-on-error for smartd; not yet enabled. - -* Sun Nov 10 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net> -- Added -P (Permissive) Directive to smartd.conf file to allow SMART monitoring of - pre-ATA-3 Rev 4 disks that have SMART but do not have a SMART capability bit. - -* Thu Nov 7 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net> -- Added a Man section 5 page for smartd.conf -- Changed Makefile so that the -V option does not reflect file state - before commit! -- modified .spec file so that locale information now contains - character set definition. Changed pt_BR to pt since we do not use any - aspect other than language. See man setlocale. -- smartctl: added new options -W, -U, and -P to control if and how the - smartctl exits if an error is detected in either a SMART data - structure checksum, or a SMART command returns an error. -- modified manual page to break options into slightly more logical - categories. -- reformatted 'usage' message order to agree with man page ordering - -* Mon Nov 4 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net> -- smartctl: added new options -n and -N to force device to be ATA or SCSI -- smartctl: no longer dies silently if device path does not start/dev/X -- smartctl: now handles arbitrary device paths -- Added additional macros for manual and sbin paths in this SPEC file. -- Modified Makefile to install /etc/smartd.conf, but without overwriting existing config file -- Modified this specfile to do the same, and to not remove any files that it did not install - -* Thu Oct 30 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net> -- Fixed typesetting error in man page smartd.8 -- Removed redundant variable (harmless) from smartd.c - -* Wed Oct 29 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net> -- Added a new directive for the configuration file. If the word - DEVICESCAN appears before any non-commented material in the - configuration file, then the confi file will be ignored and the - devices wil be scanned. -- Note: it has now been confirmed that the code modifications between - 5.0.23 and 5.0.24 have eliminated the GCC 3.2 problems. Note that - there is a GCC bug howerver, see #848 at - http://gcc.gnu.org/cgi-bin/gnatsweb.pl?database=gcc&cmd=query -- Added new Directive for Configuration file: - -C <N> This sets the time in between disk checks to be <N> - seconds apart. Note that although you can give - this Directive multiple times on different lines of - the configuration file, only the final value that - is given has an effect, and applies to all the - disks. The default value of <N> is 1800 sec, and - the minimum allowed value is ten seconds. -- Problem wasn't the print format. F.L.W. Meunier <0@pervalidus.net> - sent me a gcc 3.2 build and I ran it under a debugger. The - problem seems to be with passing the very large (2x512+4) byte - data structures as arguments. I never liked this anyway; it was - inherited from smartsuite. So I've changed all the heavyweight - functions (ATA ones, anyone) to just passing pointers, not hideous - kB size structures on the stack. Hopefully this will now build OK - under gcc 3.2 with any sensible compilation options. -- Because of reported problems with GCC 3.2 compile, I have gone - thorough the code and explicitly changed all print format - parameters to correspond EXACTLY to int unless they have to be - promoted to long longs. To quote from the glibc bible: [From - GLIBC Manual: Since the prototype doesn't specify types for - optional arguments, in a call to a variadic function the default - argument promotions are performed on the optional argument - values. This means the objects of type char or short int (whether - signed or not) are promoted to either int or unsigned int, as - required. -- smartd, smartctl now warn if they find an attribute whose ID - number does not match between Data and Threshold structures. -- Fixed nasty bug which led to wrong number of arguments for a - varargs statement, with attendent stack corruption. Sheesh! - Have added script to CVS attic to help find such nasties in the - future. - -* Tue Oct 29 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net> -- Eliminated some global variables out of header files and other - minor cleanup of smartd. -- Did some revision of the man page for smartd and made the usage - messages for Directives consistent. -- smartd: prints warning message when it gets SIGHUP, saying that it is - NOT re-reading the config file. -- smartctl: updated man page to say self-test commands -O,x,X,s,S,A - appear to be supported in the code. [I can't test these, can anyone - report?] -- smartctl: smartctl would previously print the LBA of a self-test - if it completed, and the LBA was not 0 or 0xff...f However - according to the specs this is not correct. According to the - specs, if the self-test completed without error then LBA is - undefined. This version fixes that. LBA value only printed if - self-test encountered an error. -- smartd has changed significantly. This is the first CVS checkin of - code that extends the options available for smartd. The following - options can be placed into the /etc/smartd.conf file, and control the - behavior of smartd. -- Configuration file Directives (following device name): - -A Device is an ATA device - -S Device is a SCSI device - -c Monitor SMART Health Status - -l Monitor SMART Error Log for changes - -L Monitor SMART Self-Test Log for new errors - -f Monitor for failure of any 'Usage' Attributes - -p Report changes in 'Prefailure' Attributes - -u Report changes in 'Usage' Attributes - -t Equivalent to -p and -u Directives - -a Equivalent to -c -l -L -f -t Directives - -i ID Ignore Attribute ID for -f Directive - -I ID Ignore Attribute ID for -p, -u or -t Directive - # Comment: text after a hash sign is ignored - \ Line continuation character -- cleaned up functions used for printing CVS IDs. Now use string - library, as it should be. -- modified length of device name string in smartd internal structure - to accomodate max length device name strings -- removed un-implemented (-e = Email notification) option from - command line arg list. We'll put it back on when implemeneted. -- smartd now logs serious (fatal) conditions in its operation at - loglevel LOG_CRIT rather than LOG_INFO before exiting with error. -- smartd used to open a file descriptor for each SMART enabled -- device, and then keep it open the entire time smartd was running. - This meant that some commands, like IOREADBLKPART did not work, - since the fd to the device was open. smartd now opens the device - when it needs to read values, then closes it. Also, if one time - around it can't open the device, it simply prints a warning - message but does not give up. Have eliminated the .fd field from - data structures -- no longer gets used. -- smartd now opens SCSI devices as well using O_RDONLY rather than - O_RDWR. If someone can no longer monitor a SCSI device that used - to be readable, this may well be the reason why. -- smartd never checked if the number of ata or scsi devices detected - was greater than the max number it could monitor. Now it does. - -* Fri Oct 25 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net> -- changes to the Makefile and spec file so that if there are ungzipped manual - pages in place these will be removed so that the new gzipped man pages are - visible. -- smartd on startup now looks in the configuration file /etc/smartd.conf for - a list of devices which to include in its monitoring list. See man page - (man smartd) for syntax. If not found, try all ata and ide devices. -- smartd: close file descriptors of SCSI device if not SMART capable - Closes ALL file descriptors after forking to daemon. -- added new temperature attribute (231, temperature) -- smartd: now open ATA disks using O_RDONLY - -* Thu Oct 24 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net> -- smartd now prints the name of a failed or changed attribute into logfile, - not just ID number -- Changed name of -p (print version) option to -V -- Minor change in philosophy: if a SMART command fails or the device - appears incapable of a SMART command that the user has asked for, - complain by printing an error message, but go ahead and try - anyway. Since unimplemented SMART commands should just return an - error but not cause disk problems, this should't cause any - difficulty. -- Added two new flags: q and Q. q is quiet mode - only print: For - the -l option, errors recorded in the SMART error log; For the -L - option, errors recorded in the device self-test log; For the -c - SMART "disk failing" status or device attributes (pre-failure or - usage) which failed either now or in the past; For the -v option - device attributes (pre-failure or usage) which failed either now - or in the past. Q is Very Quiet mode: Print no ouput. The only - way to learn about what was found is to use the exit status of - smartctl. -- smartctl now returns sensible values (bitmask). See smartctl.h - for the values, and the man page for documentation. -- The SMART status check now uses the correct ATA call. If failure - is detected we search through attributes to list the failed ones. - If the SMART status check shows GOOD, we then look to see if their - are any usage attributes or prefail attributes have failed at any - time. If so we print them. -- Modified function that prints vendor attributes to say if the - attribute has currently failed or has ever failed. -- -p option now prints out license info and CVS strings for all - modules in the code, nicely formatted. -- Previous versions of this code (and Smartsuite) only generate - SMART failure errors if the value of an attribute is below the - threshold and the prefailure bit is set. However the ATA Spec - (ATA4 <=Rev 4) says that it is a SMART failure if the value of an - attribute is LESS THAN OR EQUAL to the threshold and the - prefailure bit is set. This is now fixed in both smartctl and - smartd. Note that this is a troubled subject -- the original - SFF 8035i specification defining SMART was inconsistent about - this. One section says that Attribute==Threshold is pass, - and another section says it is fail. However the ATA specs are - consistent and say Attribute==Threshold is a fail. -- smartd did not print the correct value of any failing SMART attribute. It - printed the index in the attribute table, not the attribute - ID. This is fixed. -- when starting self-tests in captive mode ioctl returns EIO because - the drive has been busied out. Detect this and don't return an eror - in this case. Check this this is correct (or how to fix it?) - - fixed possible error in how to determine ATA standard support - for devices with no ATA minor revision number. -- device opened only in read-only not read-write mode. Don't need R/W - access to get smart data. Check this with Andre. -- smartctl now handles all possible choices of "multiple options" - gracefully. It goes through the following phases of operation, - in order: INFORMATION, ENABLE/DISABLE, DISPLAY DATA, RUN/ABORT TESTS. - Documentation has bee updated to explain the different phases of - operation. Control flow through ataPrintMain() - simplified. -- If reading device identity information fails, try seeing if the info - can be accessed using a "DEVICE PACKET" command. This way we can - at least get device info. -- Modified Makefile to automatically tag CVS archive on issuance of - a release -- Modified drive detection so minor device ID code showing ATA-3 rev - 0 (no SMART) is known to not be SMART capable. -- Now verify the checksum of the device ID data structure, and of the - attributes threshold structure. Before neither of these - structures had their checksums verified. -- New behavior vis-a-vis checksums. If they are wrong, we log - warning messages to stdout, stderr, and syslog, but carry on - anyway. All functions now call a checksumwarning routine if the - checksum doesn't vanish as it should. -- Changed Read Hard Disk Identity function to get fresh info from - the disk on each call rather than to use the values that were read - upon boot-up into the BIOS. This is the biggest change in this - release. The ioctl(device, HDIO_GET_IDENTITY, buf ) call should - be avoided in such code. Note that if people get garbled strings - for the model, serial no and firmware versions of their drives, - then blame goes here (the BIOS does the byte swapping for you, - apparently!) -- Function ataSmartSupport now looks at correct bits in drive - identity structure to verify first that these bits are valid, - before using them. -- Function ataIsSmartEnabled() written which uses the Drive ID state - information to tell if SMART is enabled or not. We'll carry this - along for the moment without using it. -- Function ataDoesSmartWork() guaranteed to work if the device - supports SMART. -- Replace some numbers by #define MACROS -- Wrote Function TestTime to return test time associated with each - different type of test. -- Thinking of the future, have added a new function called - ataSmartStatus2(). Eventually when I understand how to use the - TASKFILE API and am sure that this works correctly, it will - replace ataSmartStatus(). This queries the drive directly to - see if the SMART status is OK, rather than comparing thresholds to - attribute values ourselves. But I need to get some drives that fail - their SMART status to check it. - -* Thu Oct 17 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net> -- Removed extraneous space before some error message printing. -- Fixed some character buffers that were too short for contents. - Only used for unrecognized drives, so probably damage was minimal. - -* Wed Oct 16 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net> -- Initial release. Code is derived from smartsuite, and is - intended to be compatible with the ATA/ATAPI-5 specifications. -- For IBM disks whose raw temp data includes three temps. print all - three -- print timestamps for error log to msec precision -- added -m option for Hitachi disks that store power on life in - minutes -- added -L option for printing self-test error logs -- in -l option, now print power on lifetime, so that one can see - when the error took place -- updated SMART structure definitions to ATA-5 spec -- added -p option -- added -f and -F options to enable/disable autosave threshold - parameters - diff --git a/sm5/utility.c b/sm5/utility.c deleted file mode 100644 index f5698bb54..000000000 --- a/sm5/utility.c +++ /dev/null @@ -1,254 +0,0 @@ -/* - * utility.c - * - * Home page of code is: http://smartmontools.sourceforge.net - * - * Copyright (C) 2002-3 Bruce Allen <smartmontools-support@lists.sourceforge.net> - * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org> - * - * 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 Software Foundation; either version 2, or (at your option) - * any later version. - * - * You should have received a copy of the GNU General Public License - * (for example COPYING); if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * This code was originally developed as a Senior Thesis by Michael Cornwell - * at the Concurrent Systems Laboratory (now part of the Storage Systems - * Research Center), Jack Baskin School of Engineering, University of - * California, Santa Cruz. http://ssrc.soe.ucsc.edu/ - * - */ - -// THIS FILE IS INTENDED FOR UTILITY ROUTINES THAT ARE APPLICABLE TO -// BOTH SCSI AND ATA DEVICES, AND THAT MAY BE USED IN SMARTD, -// SMARTCTL, OR BOTH. - -#include <stdio.h> -#include <unistd.h> -#include <string.h> -#include <time.h> -#include <errno.h> -#include <stdlib.h> -#include <ctype.h> -#include "utility.h" - -// Any local header files should be represented by a CVSIDX just below. -const char* utility_c_cvsid="$Id: utility.c,v 1.9 2003/04/25 22:22:56 ballen4705 Exp $" UTILITY_H_CVSID; - - -// Utility function prints date and time and timezone into a character -// buffer of length>=64. All the fuss is needed to get the right -// timezone info (sigh). -void dateandtimezoneepoch(char *buffer, time_t tval){ - struct tm *tmval; - char *timezonename; - char datebuffer[64]; - - // Get the time structure. We need this to determine if we are in - // daylight savings time or not. - tmval=localtime(&tval); - - // Convert to an ASCII string, put in datebuffer - asctime_r(tmval, datebuffer); - - // Remove newline - datebuffer[strlen(datebuffer)-1]='\0'; - - // correct timezone name - if (tmval->tm_isdst==0) - // standard time zone - timezonename=tzname[0]; - else if (tmval->tm_isdst>0) - // daylight savings in effect - timezonename=tzname[1]; - else - // unable to determine if daylight savings in effect - timezonename=""; - - // Finally put the information into the buffer as needed. - snprintf(buffer, 64, "%s %s", datebuffer, timezonename); - - return; -} - -// Date and timezone gets printed into string pointed to by buffer -void dateandtimezone(char *buffer){ - - // Get the epoch (time in seconds since Jan 1 1970) - time_t tval=time(NULL); - - dateandtimezoneepoch(buffer, tval); - return; -} - -// These are two utility functions for printing CVS IDs. Massagecvs() -// returns distance that it has moved ahead in the input string -int massagecvs(char *out, const char *cvsid){ - char *copy,*filename,*date,*version; - const char delimiters[] = " ,$"; - - // make a copy on stack, go to first token, - if (!(copy=strdup(cvsid)) || !(filename=strtok(copy, delimiters))) - return 0; - - // move to first instance of "Id:" - while (strcmp(filename,"Id:")) - if (!(filename=strtok(NULL, delimiters))) - return 0; - - // get filename, skip "v", get version and date - if (!( filename=strtok(NULL, delimiters) ) || - !( strtok(NULL, delimiters) ) || - !( version=strtok(NULL, delimiters) ) || - !( date=strtok(NULL, delimiters) ) ) - return 0; - - sprintf(out,"%-13s revision: %-6s date: %-15s", filename, version, date); - free(copy); - return (date-copy)+strlen(date); -} - -// prints a single set of CVS ids -void printone(char *block, const char *cvsid){ - char strings[CVSMAXLEN]; - const char *here=cvsid; - int line=1,len=strlen(cvsid)+1; - - // check that the size of the output block is sufficient - if (len>=CVSMAXLEN) { - pout("CVSMAXLEN=%d must be at least %d\n",CVSMAXLEN,len+1); - exit(1); - } - - // loop through the different strings - while ((len=massagecvs(strings,here))){ - switch (line++){ - case 1: - block+=snprintf(block,CVSMAXLEN,"Module:"); - break; - default: - block+=snprintf(block,CVSMAXLEN," uses:"); - } - block+=snprintf(block,CVSMAXLEN," %s\n",strings); - here+=len; - } - return; -} - - -// A replacement for perror() that sends output to our choice of -// printing. -void syserror(const char *message){ - const char *errormessage; - - // Get the correct system error message: - errormessage=strerror(errno); - - // Check that caller has handed a sensible string, and provide - // appropriate output. See perrror(3) man page to understand better. - if (message && *message) - pout("%s: %s\n",message, errormessage); - else - pout("%s\n",errormessage); - - return; -} - -// Prints a warning message for a failed regular expression compilation from -// regcomp(). -void printregexwarning(int errcode, regex_t *compiled){ - size_t length = regerror(errcode, compiled, NULL, 0); - char *buffer = malloc(length); - if (!buffer){ - pout("Out of memory in printregexwarning()\n"); - return; - } - regerror(errcode, compiled, buffer, length); - pout("%s\n", buffer); - free(buffer); - return; -} - -// A wrapper for regcomp(). Returns zero for success, non-zero otherwise. -int compileregex(regex_t *compiled, const char *pattern, int cflags) -{ - int errorcode; - - if ((errorcode = regcomp(compiled, pattern, cflags))) { - pout("Internal error: unable to compile regular expression %s", pattern); - printregexwarning(errorcode, compiled); - pout("Please inform smartmontools developers\n"); - return 1; - } - return 0; -} - -// Splits an argument to the -r option into a name part and an (optional) -// positive integer part. s is a pointer to a string containing the -// argument. After the call, s will point to the name part and *i the -// integer part if there is one or 1 otherwise. Note that the string s may -// be changed by this function. Returns zero if successful and non-zero -// otherwise. -int split_report_arg(char *s, int *i) -{ - if ((s = strchr(s, ','))) { - // Looks like there's a name part and an integer part. - *s++ = '\0'; - if (*s == '0' || !isdigit(*s)) // The integer part must be positive - return 1; - errno = 0; - *i = atoi(s); - if (errno) - return 1; - } else { - // There's no integer part. - *i = 1; - } - - return 0; -} - -// Guess device type (ata or scsi) based on device name (Linux specific) -// SCSI device name in linux can be sd, sr, scd, st, nst, osst, nosst and sg. -// #define GUESS_DEVTYPE_ATA 0 -// #define GUESS_DEVTYPE_SCSI 1 -// #define GUESS_DEVTYPE_DONT_KNOW 2 -static const char * lin_dev_prefix = "/dev/"; -static const char * lin_dev_ata_disk_plus = "h"; -static const char * lin_dev_scsi_disk_plus = "s"; -static const char * lin_dev_scsi_tape1 = "ns"; -static const char * lin_dev_scsi_tape2 = "os"; -static const char * lin_dev_scsi_tape3 = "nos"; - -int guess_linux_device_type(const char * dev_name) -{ - int len; - int dev_prefix_len = strlen(lin_dev_prefix); - - if (dev_name && ((len = strlen(dev_name)) > 0)) { - if (0 == strncmp(lin_dev_prefix, dev_name, dev_prefix_len)) { - if (len <= dev_prefix_len) - return 2; - dev_name += dev_prefix_len; - } - if (0 == strncmp(lin_dev_ata_disk_plus, dev_name, - strlen(lin_dev_ata_disk_plus))) - return 0; - else if (0 == strncmp(lin_dev_scsi_disk_plus, dev_name, - strlen(lin_dev_scsi_disk_plus))) - return 1; - else if (0 == strncmp(lin_dev_scsi_tape1, dev_name, - strlen(lin_dev_scsi_tape1))) - return 1; - else if (0 == strncmp(lin_dev_scsi_tape2, dev_name, - strlen(lin_dev_scsi_tape2))) - return 1; - else if (0 == strncmp(lin_dev_scsi_tape3, dev_name, - strlen(lin_dev_scsi_tape3))) - return 1; - } - return 2; -} diff --git a/sm5/utility.cpp b/sm5/utility.cpp deleted file mode 100644 index 7e0290248..000000000 --- a/sm5/utility.cpp +++ /dev/null @@ -1,254 +0,0 @@ -/* - * utility.c - * - * Home page of code is: http://smartmontools.sourceforge.net - * - * Copyright (C) 2002-3 Bruce Allen <smartmontools-support@lists.sourceforge.net> - * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org> - * - * 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 Software Foundation; either version 2, or (at your option) - * any later version. - * - * You should have received a copy of the GNU General Public License - * (for example COPYING); if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * This code was originally developed as a Senior Thesis by Michael Cornwell - * at the Concurrent Systems Laboratory (now part of the Storage Systems - * Research Center), Jack Baskin School of Engineering, University of - * California, Santa Cruz. http://ssrc.soe.ucsc.edu/ - * - */ - -// THIS FILE IS INTENDED FOR UTILITY ROUTINES THAT ARE APPLICABLE TO -// BOTH SCSI AND ATA DEVICES, AND THAT MAY BE USED IN SMARTD, -// SMARTCTL, OR BOTH. - -#include <stdio.h> -#include <unistd.h> -#include <string.h> -#include <time.h> -#include <errno.h> -#include <stdlib.h> -#include <ctype.h> -#include "utility.h" - -// Any local header files should be represented by a CVSIDX just below. -const char* utility_c_cvsid="$Id: utility.cpp,v 1.9 2003/04/25 22:22:56 ballen4705 Exp $" UTILITY_H_CVSID; - - -// Utility function prints date and time and timezone into a character -// buffer of length>=64. All the fuss is needed to get the right -// timezone info (sigh). -void dateandtimezoneepoch(char *buffer, time_t tval){ - struct tm *tmval; - char *timezonename; - char datebuffer[64]; - - // Get the time structure. We need this to determine if we are in - // daylight savings time or not. - tmval=localtime(&tval); - - // Convert to an ASCII string, put in datebuffer - asctime_r(tmval, datebuffer); - - // Remove newline - datebuffer[strlen(datebuffer)-1]='\0'; - - // correct timezone name - if (tmval->tm_isdst==0) - // standard time zone - timezonename=tzname[0]; - else if (tmval->tm_isdst>0) - // daylight savings in effect - timezonename=tzname[1]; - else - // unable to determine if daylight savings in effect - timezonename=""; - - // Finally put the information into the buffer as needed. - snprintf(buffer, 64, "%s %s", datebuffer, timezonename); - - return; -} - -// Date and timezone gets printed into string pointed to by buffer -void dateandtimezone(char *buffer){ - - // Get the epoch (time in seconds since Jan 1 1970) - time_t tval=time(NULL); - - dateandtimezoneepoch(buffer, tval); - return; -} - -// These are two utility functions for printing CVS IDs. Massagecvs() -// returns distance that it has moved ahead in the input string -int massagecvs(char *out, const char *cvsid){ - char *copy,*filename,*date,*version; - const char delimiters[] = " ,$"; - - // make a copy on stack, go to first token, - if (!(copy=strdup(cvsid)) || !(filename=strtok(copy, delimiters))) - return 0; - - // move to first instance of "Id:" - while (strcmp(filename,"Id:")) - if (!(filename=strtok(NULL, delimiters))) - return 0; - - // get filename, skip "v", get version and date - if (!( filename=strtok(NULL, delimiters) ) || - !( strtok(NULL, delimiters) ) || - !( version=strtok(NULL, delimiters) ) || - !( date=strtok(NULL, delimiters) ) ) - return 0; - - sprintf(out,"%-13s revision: %-6s date: %-15s", filename, version, date); - free(copy); - return (date-copy)+strlen(date); -} - -// prints a single set of CVS ids -void printone(char *block, const char *cvsid){ - char strings[CVSMAXLEN]; - const char *here=cvsid; - int line=1,len=strlen(cvsid)+1; - - // check that the size of the output block is sufficient - if (len>=CVSMAXLEN) { - pout("CVSMAXLEN=%d must be at least %d\n",CVSMAXLEN,len+1); - exit(1); - } - - // loop through the different strings - while ((len=massagecvs(strings,here))){ - switch (line++){ - case 1: - block+=snprintf(block,CVSMAXLEN,"Module:"); - break; - default: - block+=snprintf(block,CVSMAXLEN," uses:"); - } - block+=snprintf(block,CVSMAXLEN," %s\n",strings); - here+=len; - } - return; -} - - -// A replacement for perror() that sends output to our choice of -// printing. -void syserror(const char *message){ - const char *errormessage; - - // Get the correct system error message: - errormessage=strerror(errno); - - // Check that caller has handed a sensible string, and provide - // appropriate output. See perrror(3) man page to understand better. - if (message && *message) - pout("%s: %s\n",message, errormessage); - else - pout("%s\n",errormessage); - - return; -} - -// Prints a warning message for a failed regular expression compilation from -// regcomp(). -void printregexwarning(int errcode, regex_t *compiled){ - size_t length = regerror(errcode, compiled, NULL, 0); - char *buffer = malloc(length); - if (!buffer){ - pout("Out of memory in printregexwarning()\n"); - return; - } - regerror(errcode, compiled, buffer, length); - pout("%s\n", buffer); - free(buffer); - return; -} - -// A wrapper for regcomp(). Returns zero for success, non-zero otherwise. -int compileregex(regex_t *compiled, const char *pattern, int cflags) -{ - int errorcode; - - if ((errorcode = regcomp(compiled, pattern, cflags))) { - pout("Internal error: unable to compile regular expression %s", pattern); - printregexwarning(errorcode, compiled); - pout("Please inform smartmontools developers\n"); - return 1; - } - return 0; -} - -// Splits an argument to the -r option into a name part and an (optional) -// positive integer part. s is a pointer to a string containing the -// argument. After the call, s will point to the name part and *i the -// integer part if there is one or 1 otherwise. Note that the string s may -// be changed by this function. Returns zero if successful and non-zero -// otherwise. -int split_report_arg(char *s, int *i) -{ - if ((s = strchr(s, ','))) { - // Looks like there's a name part and an integer part. - *s++ = '\0'; - if (*s == '0' || !isdigit(*s)) // The integer part must be positive - return 1; - errno = 0; - *i = atoi(s); - if (errno) - return 1; - } else { - // There's no integer part. - *i = 1; - } - - return 0; -} - -// Guess device type (ata or scsi) based on device name (Linux specific) -// SCSI device name in linux can be sd, sr, scd, st, nst, osst, nosst and sg. -// #define GUESS_DEVTYPE_ATA 0 -// #define GUESS_DEVTYPE_SCSI 1 -// #define GUESS_DEVTYPE_DONT_KNOW 2 -static const char * lin_dev_prefix = "/dev/"; -static const char * lin_dev_ata_disk_plus = "h"; -static const char * lin_dev_scsi_disk_plus = "s"; -static const char * lin_dev_scsi_tape1 = "ns"; -static const char * lin_dev_scsi_tape2 = "os"; -static const char * lin_dev_scsi_tape3 = "nos"; - -int guess_linux_device_type(const char * dev_name) -{ - int len; - int dev_prefix_len = strlen(lin_dev_prefix); - - if (dev_name && ((len = strlen(dev_name)) > 0)) { - if (0 == strncmp(lin_dev_prefix, dev_name, dev_prefix_len)) { - if (len <= dev_prefix_len) - return 2; - dev_name += dev_prefix_len; - } - if (0 == strncmp(lin_dev_ata_disk_plus, dev_name, - strlen(lin_dev_ata_disk_plus))) - return 0; - else if (0 == strncmp(lin_dev_scsi_disk_plus, dev_name, - strlen(lin_dev_scsi_disk_plus))) - return 1; - else if (0 == strncmp(lin_dev_scsi_tape1, dev_name, - strlen(lin_dev_scsi_tape1))) - return 1; - else if (0 == strncmp(lin_dev_scsi_tape2, dev_name, - strlen(lin_dev_scsi_tape2))) - return 1; - else if (0 == strncmp(lin_dev_scsi_tape3, dev_name, - strlen(lin_dev_scsi_tape3))) - return 1; - } - return 2; -} diff --git a/sm5/utility.h b/sm5/utility.h deleted file mode 100644 index 9b0812a1e..000000000 --- a/sm5/utility.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * utility.h - * - * Home page of code is: http://smartmontools.sourceforge.net - * - * Copyright (C) 2002-3 Bruce Allen <smartmontools-support@lists.sourceforge.net> - * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org> - * - * 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 Software Foundation; either version 2, or (at your option) - * any later version. - * - * You should have received a copy of the GNU General Public License - * (for example COPYING); if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * This code was originally developed as a Senior Thesis by Michael Cornwell - * at the Concurrent Systems Laboratory (now part of the Storage Systems - * Research Center), Jack Baskin School of Engineering, University of - * California, Santa Cruz. http://ssrc.soe.ucsc.edu/ - * - */ - -#ifndef __UTILITY_H_ -#define __UTILITY_H_ - -#ifndef UTILITY_H_CVSID -#define UTILITY_H_CVSID "$Id: utility.h,v 1.9 2003/04/22 04:23:29 dpgilbert Exp $\n" -#endif - -#include <time.h> -#include <regex.h> - -// Utility function prints current date and time and timezone into a -// character buffer of length>=64. All the fuss is needed to get the -// right timezone info (sigh). -void dateandtimezone(char *buffer); -// Same, but for time defined by epoch tval -void dateandtimezoneepoch(char *buffer, time_t tval); - - - -// utility function for printing out CVS strings -#define CVSMAXLEN 1024 -void printone(char *block, const char *cvsid); - -// like printf() except that we can control it better. Note -- -// although the prototype is given here, in utility.h, the function -// itself is defined differently in smartctl and smartd. So the -// function definition is in smartd.c and in smartctl.c. -void pout(char *fmt, ...) - __attribute__ ((format (printf, 1, 2))); - -// replacement for perror() with redirected output. -void syserror(const char *message); - -// Prints a warning message for a failed regular expression compilation from -// regcomp(). -void printregexwarning(int errcode, regex_t *compiled); - -// A wrapper for regcomp(). Returns zero for success, non-zero otherwise. -int compileregex(regex_t *compiled, const char *pattern, int cflags); - -// Function for processing -r option in smartctl and smartd -int split_report_arg(char *s, int *i); - -// Guess device type (ata or scsi) based on device name (Linux specific) -#define GUESS_DEVTYPE_ATA 0 -#define GUESS_DEVTYPE_SCSI 1 -#define GUESS_DEVTYPE_DONT_KNOW 2 -int guess_linux_device_type(const char * dev_name); - -#endif diff --git a/www/cvs-script b/www/cvs-script deleted file mode 100755 index 6974e72e2..000000000 --- a/www/cvs-script +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -# execute this script in the current shell, using for example -# . cvs_script -unset CVS_SERVER -export CVS_RSH=ssh -export CVSROOT=:ext:ballen4705@cvs.smartmontools.sourceforge.net:/cvsroot/smartmontools diff --git a/www/examples/HITACHI_DK23BA-20-0.txt b/www/examples/HITACHI_DK23BA-20-0.txt deleted file mode 100644 index 13e9cb012..000000000 --- a/www/examples/HITACHI_DK23BA-20-0.txt +++ /dev/null @@ -1,163 +0,0 @@ -[root@ballen www]# /usr/sbin/smartctl -am /dev/hda - -smartctl version 5.0-25 Copyright (C) 2002 Bruce Allen -Home page is http://smartmontools.sourceforge.net/ - -=== START OF INFORMATION SECTION === -Device Model: HITACHI_DK23BA-20 -Serial Number: 12H7M8 -Firmware Version: 00E0A0D2 -ATA Version is: 5 -ATA Standard is: ATA/ATAPI-5 T13 1321D revision 1 -SMART support is: Available - device has SMART capability. -SMART support is: Enabled - -=== START OF READ SMART DATA SECTION === -SMART overall-health self-assessment test result: PASSED -See vendor-specific Attribute list for marginal Attributes. - -General SMART Values: -Off-line data collection status: (0x00) Offline data collection activity was - never started. -Self-test execution status: ( 0) The previous self-test routine completed - without error or no self-test has ever - been run. -Total time to complete off-line -data collection: (1530) seconds. -Offline data collection -capabilities: (0x1b) SMART execute Offline immediate. - Automatic timer ON/OFF support. - Suspend Offline collection upon new - command. - Offline surface scan supported. - Self-test supported. -SMART capabilities: (0x0003) Saves SMART data before entering - power-saving mode. - Supports SMART auto save timer. -Error logging capability: (0x01) Error logging supported. -Short self-test routine -recommended polling time: ( 2) minutes. -Extended self-test routine -recommended polling time: ( 26) minutes. - -SMART Attributes Data Structure revision number: 16 -Vendor Specific SMART Attributes with Thresholds: -ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE WHEN_FAILED RAW_VALUE - 1 Raw_Read_Error_Rate 0x000d 100 083 050 Pre-fail - 677 - 3 Spin_Up_Time 0x0007 100 100 050 Pre-fail - 0 - 4 Start_Stop_Count 0x0032 100 100 050 Old_age - 249 - 5 Reallocated_Sector_Ct 0x0033 099 099 010 Pre-fail - 30 - 7 Seek_Error_Rate 0x000f 100 100 050 Pre-fail - 319 - 9 Power_On_Hours 0x0032 099 099 060 Old_age - 701 h + 42 m - 10 Spin_Retry_Count 0x0013 100 100 050 Pre-fail - 0 - 12 Power_Cycle_Count 0x0032 100 100 050 Old_age - 249 -192 Power-Off_Retract_Count 0x0032 100 100 050 Old_age - 15 -195 Hardware_ECC_Recovered 0x001a 100 001 050 Old_age In_the_past 559 -196 Reallocated_Event_Count 0x0032 097 097 001 Old_age - 30 -197 Current_Pending_Sector 0x0032 095 095 001 Old_age - 5 -198 Offline_Uncorrectable 0x0010 095 095 001 Old_age - 31 -199 UDMA_CRC_Error_Count 0x003e 200 200 000 Old_age - 0 -221 G-Sense_Error_Rate 0x000a 100 100 050 Old_age - 0 -223 Load_Retry_Count 0x0012 100 100 050 Old_age - 0 -225 Load_Cycle_Count 0x0032 095 095 050 Old_age - 18446744072753281791 -230 Unknown_Attribute 0x0032 100 100 060 Old_age - 18484 -250 Unknown_Attribute 0x000a 100 070 050 Old_age - 601 - -SMART Error Log Version: 1 -ATA Error Count: 9 (device log contains only the most recent five errors) - DCR = Device Control Register - FR = Features Register - SC = Sector Count Register - SN = Sector Number Register - CL = Cylinder Low Register - CH = Cylinder High Register - D/H = Device/Head Register - CR = Content written to Command Register - ER = Error register - STA = Status register -Timestamp is seconds since the previous disk power-on. -Note: timestamp "wraps" after 2^32 msec = 49.710 days. - -Error 1 occurred at disk power-on lifetime: 458 hours -When the command that caused the error occurred, the device was active or idle. -After command completion occurred, registers were: -ER:40 SC:01 SN:15 CL:be CH:2e D/H:e0 ST:51 -Sequence of commands leading to the command that caused the error were: -DCR FR SC SN CL CH D/H CR Timestamp - 00 00 01 15 be 2e e0 c8 831.599 - 00 00 01 14 be 2e e0 c8 831.594 - 00 00 01 13 be 2e e0 c8 831.594 - 00 00 01 12 be 2e e0 c8 831.594 - 00 00 01 11 be 2e e0 c8 831.594 - -Error 2 occurred at disk power-on lifetime: 458 hours -When the command that caused the error occurred, the device was active or idle. -After command completion occurred, registers were: -ER:40 SC:45 SN:15 CL:be CH:2e D/H:e0 ST:51 -Sequence of commands leading to the command that caused the error were: -DCR FR SC SN CL CH D/H CR Timestamp - 00 00 80 da bd 2e e0 c8 829.680 - 00 00 80 5a bd 2e e0 c8 829.677 - 00 00 80 da bc 2e e0 c8 829.673 - 00 00 80 5a bc 2e e0 c8 829.671 - 00 00 01 58 bc 2e e0 c8 829.671 - -Error 3 occurred at disk power-on lifetime: 458 hours -When the command that caused the error occurred, the device was active or idle. -After command completion occurred, registers were: -ER:40 SC:01 SN:47 CL:bc CH:2e D/H:e0 ST:51 -Sequence of commands leading to the command that caused the error were: -DCR FR SC SN CL CH D/H CR Timestamp - 00 00 01 47 bc 2e e0 c8 826.962 - 00 00 01 46 bc 2e e0 c8 826.961 - 00 00 01 45 bc 2e e0 c8 826.961 - 00 00 01 44 bc 2e e0 c8 826.961 - 00 00 01 43 bc 2e e0 c8 826.961 - -Error 4 occurred at disk power-on lifetime: 458 hours -When the command that caused the error occurred, the device was active or idle. -After command completion occurred, registers were: -ER:40 SC:13 SN:47 CL:bc CH:2e D/H:e0 ST:51 -Sequence of commands leading to the command that caused the error were: -DCR FR SC SN CL CH D/H CR Timestamp - 00 00 80 da bb 2e e0 c8 825.038 - 00 00 80 5a bb 2e e0 c8 825.033 - 00 00 80 da ba 2e e0 c8 825.030 - 00 00 80 5a ba 2e e0 c8 824.940 - 00 00 80 da b9 2e e0 c8 824.937 - -Error 5 occurred at disk power-on lifetime: 458 hours -When the command that caused the error occurred, the device was active or idle. -After command completion occurred, registers were: -ER:40 SC:01 SN:85 CL:19 CH:2c D/H:e0 ST:51 -Sequence of commands leading to the command that caused the error were: -DCR FR SC SN CL CH D/H CR Timestamp - 00 00 01 85 19 2c e0 c8 816.487 - 00 00 01 84 19 2c e0 c8 816.487 - 00 00 01 83 19 2c e0 c8 816.486 - 00 00 01 82 19 2c e0 c8 816.486 - 00 00 01 81 19 2c e0 c8 816.486 - -SMART Self-test log, version number 1 -Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error -# 1 Short off-line Completed 00% 691 -# 2 Extended off-line Completed: read failure 40% 661 0x002c1985 -# 3 Extended off-line Completed: read failure 40% 661 0x002c1985 -# 4 Short off-line Completed 00% 660 -# 5 Extended off-line Completed: read failure 40% 658 0x002c1985 -# 6 Short off-line Completed 00% 658 -# 7 Short off-line Completed 00% 658 -# 8 Extended off-line Completed: read failure 40% 658 0x002c1985 -# 9 Extended off-line Completed: read failure 40% 657 0x002c1985 -#10 Short off-line Completed 00% 647 -#11 Short off-line Completed 00% 587 -#12 Short off-line Completed 00% 583 -#13 Short off-line Completed 00% 551 -#14 Short captive Interrupted (host reset) 40% 551 -#15 Short off-line Completed 00% 551 -#16 Extended off-line Completed: read failure 40% 550 0x002c1985 -#17 Extended off-line Aborted by host 50% 550 -#18 Short off-line Completed 00% 550 -#19 Short off-line Completed 00% 537 -#20 Extended off-line Completed: read failure 40% 536 0x002c1985 -#21 Short off-line Completed 00% 536 diff --git a/www/examples/IC35L120AVV207-0.txt b/www/examples/IC35L120AVV207-0.txt deleted file mode 100644 index 4e43e8c2d..000000000 --- a/www/examples/IC35L120AVV207-0.txt +++ /dev/null @@ -1,67 +0,0 @@ -# smartctl -a /dev/hda -smartctl version 5.0-45 Copyright (C) 2002 Bruce Allen -Home page is http://smartmontools.sourceforge.net/ - -=== START OF INFORMATION SECTION === -Device Model: IC35L120AVV207-0 -Serial Number: VNVD02G4G4BDEG -Firmware Version: V24OA63A -ATA Version is: 6 -ATA Standard is: ATA/ATAPI-6 T13 1410D revision 3a -SMART support is: Available - device has SMART capability. -SMART support is: Enabled - -=== START OF READ SMART DATA SECTION === -SMART overall-health self-assessment test result: PASSED - -General SMART Values: -Off-line data collection status: (0x00) Offline data collection activity was - never started. -Self-test execution status: ( 0) The previous self-test routine completed - without error or no self-test has ever - been run. -Total time to complete off-line -data collection: (2855) seconds. -Offline data collection -capabilities: (0x1b) SMART execute Offline immediate. - Automatic timer ON/OFF support. - Suspend Offline collection upon new - command. - Offline surface scan supported. - Self-test supported. -SMART capabilities: (0x0003) Saves SMART data before entering - power-saving mode. - Supports SMART auto save timer. -Error logging capability: (0x01) Error logging supported. -Short self-test routine -recommended polling time: ( 1) minutes. -Extended self-test routine -recommended polling time: ( 48) minutes. - -SMART Attributes Data Structure revision number: 16 -Vendor Specific SMART Attributes with Thresholds: -ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE WHEN_FAILED RAW_VALUE - 1 Raw_Read_Error_Rate 0x000b 100 100 060 Pre-fail - 0 - 2 Throughput_Performance 0x0005 100 100 050 Pre-fail - 0 - 3 Spin_Up_Time 0x0007 102 102 024 Pre-fail - 16974103 - 4 Start_Stop_Count 0x0012 100 100 000 Old_age - 14 - 5 Reallocated_Sector_Ct 0x0033 100 100 005 Pre-fail - 0 - 7 Seek_Error_Rate 0x000b 100 100 067 Pre-fail - 0 - 8 Seek_Time_Performance 0x0005 100 100 020 Pre-fail - 0 - 9 Power_On_Hours 0x0012 100 100 000 Old_age - 242 - 10 Spin_Retry_Count 0x0013 100 100 060 Pre-fail - 0 - 12 Power_Cycle_Count 0x0032 100 100 000 Old_age - 14 -192 Power-Off_Retract_Count 0x0032 100 100 050 Old_age - 24 -193 Load_Cycle_Count 0x0012 100 100 050 Old_age - 24 -194 Temperature_Celsius 0x0002 203 203 000 Old_age - 27 (Lifetime Min/Max 20/37) -196 Reallocated_Event_Count 0x0032 100 100 000 Old_age - 0 -197 Current_Pending_Sector 0x0022 100 100 000 Old_age - 0 -198 Offline_Uncorrectable 0x0008 100 100 000 Old_age - 0 -199 UDMA_CRC_Error_Count 0x000a 200 200 000 Old_age - 0 - -SMART Error Log Version: 1 -No Errors Logged - -SMART Self-test log, version number 1 -Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error -# 1 Extended off-line Completed 00% 54 diff --git a/www/examples/IC35L120AVVA07-0-0.txt b/www/examples/IC35L120AVVA07-0-0.txt deleted file mode 100644 index 57926ccfb..000000000 --- a/www/examples/IC35L120AVVA07-0-0.txt +++ /dev/null @@ -1,69 +0,0 @@ -smartctl version 5.0-24 Copyright (C) 2002 Bruce Allen -Home page is http://smartmontools.sourceforge.net/ - -=== START OF INFORMATION SECTION === -Device Model: IC35L120AVVA07-0 -Serial Number: VNC605A6GG8W8A -Firmware Version: VA6OA52A -ATA Version is: 5 -ATA Standard is: ATA/ATAPI-5 T13 1321D revision 1 -SMART support is: Available - device has SMART capability. -SMART support is: Enabled - -=== START OF READ SMART DATA SECTION === -SMART overall-health self-assessment test result: PASSED - -General SMART Values: -Off-line data collection status: (0x00) Offline data collection activity was - never started. -Self-test execution status: ( 0) The previous self-test routine completed - without error or no self-test has ever - been run. -Total time to complete off-line -data collection: (3399) seconds. -Offline data collection -capabilities: (0x1b) SMART execute Offline immediate. - Automatic timer ON/OFF support. - Suspend Offline collection upon new - command. - Offline surface scan supported. - Self-test supported. -SMART capabilities: (0x0003) Saves SMART data before entering - power-saving mode. - Supports SMART auto save timer. -Error logging capability: (0x01) Error logging supported. -Short self-test routine -recommended polling time: ( 1) minutes. -Extended self-test routine -recommended polling time: ( 57) minutes. - -SMART Attributes Data Structure revision number: 16 -Vendor Specific SMART Attributes with Thresholds: -ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE WHEN_FAILED RAW_VALUE - 1 Raw_Read_Error_Rate 0x000b 100 100 060 Pre-fail - 0 - 2 Throughput_Performance 0x0005 147 147 050 Pre-fail - 266 - 3 Spin_Up_Time 0x0007 093 093 024 Pre-fail - 23593335 - 4 Start_Stop_Count 0x0012 100 100 000 Old_age - 13 - 5 Reallocated_Sector_Ct 0x0033 100 100 005 Pre-fail - 0 - 7 Seek_Error_Rate 0x000b 100 100 067 Pre-fail - 0 - 8 Seek_Time_Performance 0x0005 138 138 020 Pre-fail - 30 - 9 Power_On_Hours 0x0012 100 100 000 Old_age - 554 - 10 Spin_Retry_Count 0x0013 100 100 060 Pre-fail - 0 - 12 Power_Cycle_Count 0x0032 100 100 000 Old_age - 13 -192 Power-Off_Retract_Count 0x0032 100 100 050 Old_age - 36 -193 Load_Cycle_Count 0x0012 100 100 050 Old_age - 36 -194 Temperature_Centigrade 0x0002 183 183 000 Old_age - 30 (Lifetime Min/Max 23/39) -196 Reallocated_Event_Count 0x0032 100 100 000 Old_age - 0 -197 Current_Pending_Sector 0x0022 100 100 000 Old_age - 0 -198 Offline_Uncorrectable 0x0008 100 100 000 Old_age - 0 -199 UDMA_CRC_Error_Count 0x000a 200 200 000 Old_age - 0 - -SMART Error Log Version: 1 -No Errors Logged - -SMART Self-test log, version number 1 -Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error -# 1 Extended off-line Completed 00% 492 -# 2 Short off-line Completed 00% 296 -# 3 Extended off-line Completed 00% 169 -# 4 Short off-line Completed 00% 168 diff --git a/www/examples/IC35L120AVVA07-0-1.txt b/www/examples/IC35L120AVVA07-0-1.txt deleted file mode 100644 index 992a620ce..000000000 --- a/www/examples/IC35L120AVVA07-0-1.txt +++ /dev/null @@ -1,67 +0,0 @@ -smartctl version 5.0-24 Copyright (C) 2002 Bruce Allen -Home page is http://smartmontools.sourceforge.net/ - -=== START OF INFORMATION SECTION === -Device Model: IC35L120AVVA07-0 -Serial Number: VNC605A6GEWZDA -Firmware Version: VA6OA52A -ATA Version is: 5 -ATA Standard is: ATA/ATAPI-5 T13 1321D revision 1 -SMART support is: Available - device has SMART capability. -SMART support is: Enabled - -=== START OF READ SMART DATA SECTION === -SMART overall-health self-assessment test result: PASSED - -General SMART Values: -Off-line data collection status: (0x00) Offline data collection activity was - never started. -Self-test execution status: ( 0) The previous self-test routine completed - without error or no self-test has ever - been run. -Total time to complete off-line -data collection: (3399) seconds. -Offline data collection -capabilities: (0x1b) SMART execute Offline immediate. - Automatic timer ON/OFF support. - Suspend Offline collection upon new - command. - Offline surface scan supported. - Self-test supported. -SMART capabilities: (0x0003) Saves SMART data before entering - power-saving mode. - Supports SMART auto save timer. -Error logging capability: (0x01) Error logging supported. -Short self-test routine -recommended polling time: ( 1) minutes. -Extended self-test routine -recommended polling time: ( 57) minutes. - -SMART Attributes Data Structure revision number: 16 -Vendor Specific SMART Attributes with Thresholds: -ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE WHEN_FAILED RAW_VALUE - 1 Raw_Read_Error_Rate 0x000b 100 100 060 Pre-fail - 0 - 2 Throughput_Performance 0x0005 100 100 050 Pre-fail - 0 - 3 Spin_Up_Time 0x0007 098 098 024 Pre-fail - 22348126 - 4 Start_Stop_Count 0x0012 100 100 000 Old_age - 13 - 5 Reallocated_Sector_Ct 0x0033 100 100 005 Pre-fail - 0 - 7 Seek_Error_Rate 0x000b 100 100 067 Pre-fail - 0 - 8 Seek_Time_Performance 0x0005 100 100 020 Pre-fail - 0 - 9 Power_On_Hours 0x0012 100 100 000 Old_age - 554 - 10 Spin_Retry_Count 0x0013 100 100 060 Pre-fail - 0 - 12 Power_Cycle_Count 0x0032 100 100 000 Old_age - 13 -192 Power-Off_Retract_Count 0x0032 100 100 050 Old_age - 36 -193 Load_Cycle_Count 0x0012 100 100 050 Old_age - 36 -194 Temperature_Centigrade 0x0002 189 189 000 Old_age - 29 (Lifetime Min/Max 23/36) -196 Reallocated_Event_Count 0x0032 100 100 000 Old_age - 0 -197 Current_Pending_Sector 0x0022 100 100 000 Old_age - 0 -198 Offline_Uncorrectable 0x0008 100 100 000 Old_age - 0 -199 UDMA_CRC_Error_Count 0x000a 200 200 000 Old_age - 0 - -SMART Error Log Version: 1 -No Errors Logged - -SMART Self-test log, version number 1 -Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error -# 1 Extended off-line Completed 00% 492 -# 2 Extended off-line Completed 00% 169 diff --git a/www/examples/MAXTOR-0.txt b/www/examples/MAXTOR-0.txt deleted file mode 100644 index 13e0eb28e..000000000 --- a/www/examples/MAXTOR-0.txt +++ /dev/null @@ -1,139 +0,0 @@ -smartctl version 5.0-24 Copyright (C) 2002 Bruce Allen -Home page is http://smartmontools.sourceforge.net/ - -=== START OF INFORMATION SECTION === -Device Model: MAXTOR 4K080H4 -Serial Number: 674205306226 -Firmware Version: A08.1500 -ATA Version is: 5 -ATA Standard is: ATA/ATAPI-5 T13 1321D revision 1 -SMART support is: Available - device has SMART capability. -SMART support is: Enabled - -=== START OF READ SMART DATA SECTION === -SMART overall-health self-assessment test result: PASSED - -General SMART Values: -Off-line data collection status: (0x02) Offline data collection activity - completed without error. -Self-test execution status: ( 112) The previous self-test completed having - the read element of the test failed. -Total time to complete off-line -data collection: ( 44) seconds. -Offline data collection -capabilities: (0x1b) SMART execute Offline immediate. - Automatic timer ON/OFF support. - Suspend Offline collection upon new - command. - Offline surface scan supported. - Self-test supported. -SMART capabilities: (0x0003) Saves SMART data before entering - power-saving mode. - Supports SMART auto save timer. -Error logging capability: (0x01) Error logging supported. -Short self-test routine -recommended polling time: ( 2) minutes. -Extended self-test routine -recommended polling time: ( 50) minutes. - -SMART Attributes Data Structure revision number: 11 -Vendor Specific SMART Attributes with Thresholds: -ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE WHEN_FAILED RAW_VALUE - 1 Raw_Read_Error_Rate 0x0029 100 253 020 Pre-fail - 0 - 3 Spin_Up_Time 0x0027 077 077 020 Pre-fail - 2909 - 4 Start_Stop_Count 0x0032 100 100 008 Old_age - 29 - 5 Reallocated_Sector_Ct 0x0033 100 100 020 Pre-fail - 1 - 7 Seek_Error_Rate 0x000b 100 100 023 Pre-fail - 0 - 9 Power_On_Hours 0x0012 097 097 001 Old_age - 1992 - 10 Spin_Retry_Count 0x0026 100 100 000 Old_age - 0 - 11 Calibration_Retry_Count 0x0013 100 100 020 Pre-fail - 0 - 12 Power_Cycle_Count 0x0032 100 100 008 Old_age - 29 - 13 Read_Soft_Error_Rate 0x000b 100 100 023 Pre-fail - 0 -194 Temperature_Centigrade 0x0022 093 090 042 Old_age - 19 -195 Hardware_ECC_Recovered 0x001a 100 006 000 Old_age - 7683906 -196 Reallocated_Event_Count 0x0010 099 099 020 Old_age - 1 -197 Current_Pending_Sector 0x0032 100 100 020 Old_age - 1 -198 Offline_Uncorrectable 0x0010 100 100 000 Old_age - 0 -199 UDMA_CRC_Error_Count 0x001a 198 198 000 Old_age - 2 - -SMART Error Log Version: 1 -ATA Error Count: 11 (device log contains only the most recent five errors) - DCR = Device Control Register - FR = Features Register - SC = Sector Count Register - SN = Sector Number Register - CL = Cylinder Low Register - CH = Cylinder High Register - D/H = Device/Head Register - CR = Content written to Command Register - ER = Error register - STA = Status register -Timestamp is seconds since the previous disk power-on. -Note: timestamp "wraps" after 2^32 msec = 49.710 days. - -Error 1 occurred at disk power-on lifetime: 1029 hours -When the command that caused the error occurred, the device was in an unknown state. -After command completion occurred, registers were: -ER:40 SC:02 SN:41 CL:2d CH:70 D/H:e8 ST:d1 -Sequence of commands leading to the command that caused the error were: -DCR FR SC SN CL CH D/H CR Timestamp - 70 08 02 41 2d 70 e8 c4 90.713 - 70 08 04 3f 2d 70 e8 c4 86.648 - 70 08 06 3d 2d 70 e8 c4 82.584 - 70 08 08 3b 2d 70 e8 c4 78.342 - 28 08 04 8b 2c 28 e8 c5 78.341 - -Error 2 occurred at disk power-on lifetime: 1029 hours -When the command that caused the error occurred, the device was in an unknown state. -After command completion occurred, registers were: -ER:40 SC:04 SN:3f CL:2d CH:70 D/H:e8 ST:d1 -Sequence of commands leading to the command that caused the error were: -DCR FR SC SN CL CH D/H CR Timestamp - 70 08 04 3f 2d 70 e8 c4 86.648 - 70 08 06 3d 2d 70 e8 c4 82.584 - 70 08 08 3b 2d 70 e8 c4 78.342 - 28 08 04 8b 2c 28 e8 c5 78.341 - 28 08 08 4b 2c 28 e8 c5 78.339 - -Error 3 occurred at disk power-on lifetime: 1029 hours -When the command that caused the error occurred, the device was in an unknown state. -After command completion occurred, registers were: -ER:40 SC:06 SN:3d CL:2d CH:70 D/H:e8 ST:d1 -Sequence of commands leading to the command that caused the error were: -DCR FR SC SN CL CH D/H CR Timestamp - 70 08 06 3d 2d 70 e8 c4 82.584 - 70 08 08 3b 2d 70 e8 c4 78.342 - 28 08 04 8b 2c 28 e8 c5 78.341 - 28 08 08 4b 2c 28 e8 c5 78.339 - 28 08 08 0b 2c 28 e8 c5 78.338 - -Error 4 occurred at disk power-on lifetime: 1029 hours -When the command that caused the error occurred, the device was in an unknown state. -After command completion occurred, registers were: -ER:40 SC:08 SN:3b CL:2d CH:70 D/H:e8 ST:d1 -Sequence of commands leading to the command that caused the error were: -DCR FR SC SN CL CH D/H CR Timestamp - 70 08 08 3b 2d 70 e8 c4 78.342 - 28 08 04 8b 2c 28 e8 c5 78.341 - 28 08 08 4b 2c 28 e8 c5 78.339 - 28 08 08 0b 2c 28 e8 c5 78.338 - 28 08 08 cb 2b 28 e8 c5 78.337 - -Error 5 occurred at disk power-on lifetime: 1029 hours -When the command that caused the error occurred, the device was in an unknown state. -After command completion occurred, registers were: -ER:40 SC:66 SN:41 CL:2d CH:70 D/H:e8 ST:d1 -Sequence of commands leading to the command that caused the error were: -DCR FR SC SN CL CH D/H CR Timestamp - 70 08 66 41 2d 70 e8 c4 69.020 - 70 08 68 3f 2d 70 e8 c4 64.956 - 70 08 6a 3d 2d 70 e8 c4 60.891 - 70 08 6c 3b 2d 70 e8 c4 56.826 - 70 08 fe a9 2c 70 e8 c4 52.713 - -SMART Self-test log, version number 1 -Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error -# 1 Extended off-line Completed: read failure 90% 1965 0x08702f11 -# 2 Short off-line Completed 00% 1800 -# 3 Short off-line Completed 00% 1778 -# 4 Short off-line Completed 00% 1777 diff --git a/www/examples/MAXTOR-1.txt b/www/examples/MAXTOR-1.txt deleted file mode 100644 index b1ed8ace3..000000000 --- a/www/examples/MAXTOR-1.txt +++ /dev/null @@ -1,143 +0,0 @@ -smartctl version 5.0-24 Copyright (C) 2002 Bruce Allen -Home page is http://smartmontools.sourceforge.net/ - -=== START OF INFORMATION SECTION === -Device Model: MAXTOR 4K080H4 -Serial Number: 674119123435 -Firmware Version: A08.1500 -ATA Version is: 5 -ATA Standard is: ATA/ATAPI-5 T13 1321D revision 1 -SMART support is: Available - device has SMART capability. -SMART support is: Enabled - -=== START OF READ SMART DATA SECTION === -SMART overall-health self-assessment test result: FAILED! -Drive failure expected in less than 24 hours. SAVE ALL DATA. -See vendor-specific Attribute list for failed Attributes. - -General SMART Values: -Off-line data collection status: (0x04) Offline data collection activity was - suspended by an interrupting command from host. -Self-test execution status: ( 89) The previous self-test completed having - the electrical element of the test - failed. -Total time to complete off-line -data collection: (2536) seconds. -Offline data collection -capabilities: (0x1b) SMART execute Offline immediate. - Automatic timer ON/OFF support. - Suspend Offline collection upon new - command. - Offline surface scan supported. - Self-test supported. -SMART capabilities: (0x0003) Saves SMART data before entering - power-saving mode. - Supports SMART auto save timer. -Error logging capability: (0x01) Error logging supported. -Short self-test routine -recommended polling time: ( 2) minutes. -Extended self-test routine -recommended polling time: ( 50) minutes. - -SMART Attributes Data Structure revision number: 11 -Vendor Specific SMART Attributes with Thresholds: -ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE WHEN_FAILED RAW_VALUE - 1 Raw_Read_Error_Rate 0x0029 100 253 020 Pre-fail - 0 - 3 Spin_Up_Time 0x0027 074 074 020 Pre-fail - 3294 - 4 Start_Stop_Count 0x0032 100 100 008 Old_age - 32 - 5 Reallocated_Sector_Ct 0x0033 001 001 020 Pre-fail FAILING_NOW 499 - 7 Seek_Error_Rate 0x000b 100 001 023 Pre-fail In_the_past 0 - 9 Power_On_Hours 0x0012 086 086 001 Old_age - 9812 - 10 Spin_Retry_Count 0x0026 100 100 000 Old_age - 0 - 11 Calibration_Retry_Count 0x0013 100 100 020 Pre-fail - 0 - 12 Power_Cycle_Count 0x0032 100 100 008 Old_age - 32 - 13 Read_Soft_Error_Rate 0x000b 100 001 023 Pre-fail In_the_past 0 -194 Temperature_Centigrade 0x0022 091 086 042 Old_age - 24 -195 Hardware_ECC_Recovered 0x001a 006 004 000 Old_age - 417912090 -196 Reallocated_Event_Count 0x0010 100 100 020 Old_age - 0 -197 Current_Pending_Sector 0x0032 033 032 020 Old_age - 338 -198 Offline_Uncorrectable 0x0010 100 100 000 Old_age - 0 -199 UDMA_CRC_Error_Count 0x001a 200 200 000 Old_age - 0 - -SMART Error Log Version: 1 -ATA Error Count: 20255 (device log contains only the most recent five errors) - DCR = Device Control Register - FR = Features Register - SC = Sector Count Register - SN = Sector Number Register - CL = Cylinder Low Register - CH = Cylinder High Register - D/H = Device/Head Register - CR = Content written to Command Register - ER = Error register - STA = Status register -Timestamp is seconds since the previous disk power-on. -Note: timestamp "wraps" after 2^32 msec = 49.710 days. - -Error 1 occurred at disk power-on lifetime: 9574 hours -When the command that caused the error occurred, the device was in a vendor specific or reserved state. -After command completion occurred, registers were: -ER:40 SC:60 SN:b8 CL:c6 CH:02 D/H:e5 ST:d1 -Sequence of commands leading to the command that caused the error were: -DCR FR SC SN CL CH D/H CR Timestamp - 02 05 60 b8 c6 02 e5 c4 474.857 - 02 05 f8 20 c6 02 e5 c4 470.748 - 02 05 08 18 c6 02 e5 c4 470.746 - 00 00 f8 20 c5 02 e5 c4 470.732 - 00 00 08 18 c5 02 e5 c4 470.730 - -Error 2 occurred at disk power-on lifetime: 9574 hours -When the command that caused the error occurred, the device was in a vendor specific or reserved state. -After command completion occurred, registers were: -ER:40 SC:68 SN:b0 CL:c6 CH:02 D/H:e5 ST:d1 -Sequence of commands leading to the command that caused the error were: -DCR FR SC SN CL CH D/H CR Timestamp - 02 05 f8 20 c6 02 e5 c4 470.748 - 02 05 08 18 c6 02 e5 c4 470.746 - 00 00 f8 20 c5 02 e5 c4 470.732 - 00 00 08 18 c5 02 e5 c4 470.730 - 02 05 f8 20 c4 02 e5 c4 470.717 - -Error 3 occurred at disk power-on lifetime: 9574 hours -When the command that caused the error occurred, the device was in a vendor specific or reserved state. -After command completion occurred, registers were: -ER:40 SC:08 SN:c0 CL:3e CH:0e D/H:e5 ST:d1 -Sequence of commands leading to the command that caused the error were: -DCR FR SC SN CL CH D/H CR Timestamp - 0e 05 08 c0 3e 0e e5 c4 181.677 - d0 04 08 b0 67 d0 e4 c5 181.651 - 0e 05 08 a0 45 0e e5 c4 181.646 - 0e 05 80 20 43 0e e5 c4 181.635 - 0e 05 80 20 41 0e e5 c4 181.622 - -Error 4 occurred at disk power-on lifetime: 9574 hours -When the command that caused the error occurred, the device was in a vendor specific or reserved state. -After command completion occurred, registers were: -ER:40 SC:60 SN:c0 CL:3e CH:0e D/H:e5 ST:d1 -Sequence of commands leading to the command that caused the error were: -DCR FR SC SN CL CH D/H CR Timestamp - 0e 05 80 a0 3e 0e e5 c4 172.530 - 0e 05 80 20 3d 0e e5 c4 172.335 - 0e 05 80 20 3c 0e e5 c4 164.744 - 0e 05 10 10 3b 0e e5 c4 164.736 - 0e 05 f8 18 3a 0e e5 c4 157.202 - -Error 5 occurred at disk power-on lifetime: 9574 hours -When the command that caused the error occurred, the device was in a vendor specific or reserved state. -After command completion occurred, registers were: -ER:40 SC:c0 SN:18 CL:04 CH:d3 D/H:e4 ST:d1 -Sequence of commands leading to the command that caused the error were: -DCR FR SC SN CL CH D/H CR Timestamp - d3 04 c0 18 04 d3 e4 c4 502.837 - d3 04 f8 e0 03 d3 e4 c4 498.739 - d3 04 f8 e8 02 d3 e4 c4 498.716 - 55 01 c8 90 70 55 e1 c4 498.705 - 55 01 38 48 70 55 e1 c4 498.680 - -SMART Self-test log, version number 1 -Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error -# 1 Short off-line Completed: electrical failure 90% 9786 -# 2 Extended captive Completed: servo/seek failure 90% 9676 0x04b7ed3d -# 3 Extended captive Completed 00% 9575 -# 4 Extended off-line Completed 00% 9432 -# 5 Extended off-line Completed 00% 9415 diff --git a/www/examples/MAXTOR-2.txt b/www/examples/MAXTOR-2.txt deleted file mode 100644 index 9ff60ffcb..000000000 --- a/www/examples/MAXTOR-2.txt +++ /dev/null @@ -1,79 +0,0 @@ -smartctl version 5.0-24 Copyright (C) 2002 Bruce Allen -Home page is http://smartmontools.sourceforge.net/ - -=== START OF INFORMATION SECTION === -Device Model: MAXTOR 4K080H4 -Serial Number: 674119113862 -Firmware Version: A08.1500 -ATA Version is: 5 -ATA Standard is: ATA/ATAPI-5 T13 1321D revision 1 -SMART support is: Available - device has SMART capability. -SMART support is: Enabled - -=== START OF READ SMART DATA SECTION === -SMART overall-health self-assessment test result: PASSED -See vendor-specific Attribute list for marginal Attributes. - -General SMART Values: -Off-line data collection status: (0x05) Offline data collection activity was - aborted by an interrupting command from host. -Self-test execution status: ( 0) The previous self-test routine completed - without error or no self-test has ever - been run. -Total time to complete off-line -data collection: ( 44) seconds. -Offline data collection -capabilities: (0x1b) SMART execute Offline immediate. - Automatic timer ON/OFF support. - Suspend Offline collection upon new - command. - Offline surface scan supported. - Self-test supported. -SMART capabilities: (0x0003) Saves SMART data before entering - power-saving mode. - Supports SMART auto save timer. -Error logging capability: (0x01) Error logging supported. -Short self-test routine -recommended polling time: ( 2) minutes. -Extended self-test routine -recommended polling time: ( 50) minutes. - -SMART Attributes Data Structure revision number: 11 -Vendor Specific SMART Attributes with Thresholds: -ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE WHEN_FAILED RAW_VALUE - 1 Raw_Read_Error_Rate 0x0029 100 253 020 Pre-fail - 0 - 3 Spin_Up_Time 0x0027 075 075 020 Pre-fail - 3249 - 4 Start_Stop_Count 0x0032 100 100 008 Old_age - 31 - 5 Reallocated_Sector_Ct 0x0033 100 100 020 Pre-fail - 0 - 7 Seek_Error_Rate 0x000b 100 001 023 Pre-fail In_the_past 0 - 9 Power_On_Hours 0x0012 086 086 001 Old_age - 9754 - 10 Spin_Retry_Count 0x0026 100 100 000 Old_age - 0 - 11 Calibration_Retry_Count 0x0013 100 100 020 Pre-fail - 0 - 12 Power_Cycle_Count 0x0032 100 100 008 Old_age - 31 - 13 Read_Soft_Error_Rate 0x000b 100 100 023 Pre-fail - 0 -194 Temperature_Centigrade 0x0022 035 032 042 Old_age FAILING_NOW 168 -195 Hardware_ECC_Recovered 0x001a 100 002 000 Old_age - 880099716 -196 Reallocated_Event_Count 0x0010 100 100 020 Old_age - 0 -197 Current_Pending_Sector 0x0032 100 100 020 Old_age - 0 -198 Offline_Uncorrectable 0x0010 100 253 000 Old_age - 0 -199 UDMA_CRC_Error_Count 0x001a 200 200 000 Old_age - 0 - -SMART Error Log Version: 1 -No Errors Logged - -SMART Self-test log, version number 1 -Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error -# 1 Short off-line Completed 00% 9691 -# 2 Short captive Completed 00% 9691 -# 3 Extended captive Completed 00% 9618 -# 4 Extended captive Interrupted (host reset) 90% 9563 -# 5 Short captive Completed 00% 9563 -# 6 Short off-line Completed 00% 9563 -# 7 Short captive Completed 00% 9545 -# 8 Extended off-line Completed 00% 9541 -# 9 Short captive Completed 00% 9541 -#10 Extended off-line Completed 00% 9537 -#11 Extended off-line Completed 00% 9536 -#12 Extended off-line Interrupted (host reset) 90% 9534 -#13 Extended off-line Completed 00% 9517 -#14 Extended off-line Completed 00% 9484 diff --git a/www/examples/MAXTOR-3.txt b/www/examples/MAXTOR-3.txt deleted file mode 100644 index 26df69e59..000000000 --- a/www/examples/MAXTOR-3.txt +++ /dev/null @@ -1,67 +0,0 @@ -smartctl version 5.0-24 Copyright (C) 2002 Bruce Allen -Home page is http://smartmontools.sourceforge.net/ - -=== START OF INFORMATION SECTION === -Device Model: MAXTOR 6L080J4 -Serial Number: 664201100034 -Firmware Version: A93.0500 -ATA Version is: 5 -ATA Standard is: ATA/ATAPI-5 T13 1321D revision 1 -SMART support is: Available - device has SMART capability. -SMART support is: Enabled - -=== START OF READ SMART DATA SECTION === -SMART overall-health self-assessment test result: PASSED - -General SMART Values: -Off-line data collection status: (0x00) Offline data collection activity was - never started. -Self-test execution status: ( 0) The previous self-test routine completed - without error or no self-test has ever - been run. -Total time to complete off-line -data collection: ( 35) seconds. -Offline data collection -capabilities: (0x1b) SMART execute Offline immediate. - Automatic timer ON/OFF support. - Suspend Offline collection upon new - command. - Offline surface scan supported. - Self-test supported. -SMART capabilities: (0x0003) Saves SMART data before entering - power-saving mode. - Supports SMART auto save timer. -Error logging capability: (0x01) Error logging supported. -Short self-test routine -recommended polling time: ( 2) minutes. -Extended self-test routine -recommended polling time: ( 40) minutes. - -SMART Attributes Data Structure revision number: 11 -Vendor Specific SMART Attributes with Thresholds: -ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE WHEN_FAILED RAW_VALUE - 1 Raw_Read_Error_Rate 0x0029 100 253 020 Pre-fail - 0 - 3 Spin_Up_Time 0x0027 069 066 020 Pre-fail - 3984 - 4 Start_Stop_Count 0x0032 100 100 008 Old_age - 110 - 5 Reallocated_Sector_Ct 0x0033 100 100 020 Pre-fail - 0 - 7 Seek_Error_Rate 0x000b 100 100 023 Pre-fail - 0 - 9 Power_On_Hours 0x0012 099 099 001 Old_age - 1294 - 10 Spin_Retry_Count 0x0026 100 100 000 Old_age - 0 - 11 Calibration_Retry_Count 0x0013 100 100 020 Pre-fail - 0 - 12 Power_Cycle_Count 0x0032 100 100 008 Old_age - 110 - 13 Read_Soft_Error_Rate 0x000b 100 100 023 Pre-fail - 0 -194 Temperature_Centigrade 0x0022 092 087 042 Old_age - 22 -195 Hardware_ECC_Recovered 0x001a 100 100 000 Old_age - 1163 -196 Reallocated_Event_Count 0x0010 100 100 020 Old_age - 0 -197 Current_Pending_Sector 0x0032 100 100 020 Old_age - 0 -198 Offline_Uncorrectable 0x0010 100 253 000 Old_age - 0 -199 UDMA_CRC_Error_Count 0x001a 200 200 000 Old_age - 0 - -SMART Error Log Version: 1 -No Errors Logged - -SMART Self-test log, version number 1 -Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error -# 1 Extended off-line Completed 00% 1038 -# 2 Extended off-line Aborted by host 00% 786 -# 3 Extended off-line Aborted by host 00% 786 diff --git a/www/examples/MAXTOR-4.txt b/www/examples/MAXTOR-4.txt deleted file mode 100644 index 65ae2850d..000000000 --- a/www/examples/MAXTOR-4.txt +++ /dev/null @@ -1,65 +0,0 @@ -smartctl version 5.0-24 Copyright (C) 2002 Bruce Allen -Home page is http://smartmontools.sourceforge.net/ - -=== START OF INFORMATION SECTION === -Device Model: MAXTOR 6L080J4 -Serial Number: 664205757172 -Firmware Version: A93.0500 -ATA Version is: 5 -ATA Standard is: ATA/ATAPI-5 T13 1321D revision 1 -SMART support is: Available - device has SMART capability. -SMART support is: Enabled - -=== START OF READ SMART DATA SECTION === -SMART overall-health self-assessment test result: PASSED - -General SMART Values: -Off-line data collection status: (0x04) Offline data collection activity was - suspended by an interrupting command from host. -Self-test execution status: ( 0) The previous self-test routine completed - without error or no self-test has ever - been run. -Total time to complete off-line -data collection: ( 35) seconds. -Offline data collection -capabilities: (0x1b) SMART execute Offline immediate. - Automatic timer ON/OFF support. - Suspend Offline collection upon new - command. - Offline surface scan supported. - Self-test supported. -SMART capabilities: (0x0003) Saves SMART data before entering - power-saving mode. - Supports SMART auto save timer. -Error logging capability: (0x01) Error logging supported. -Short self-test routine -recommended polling time: ( 2) minutes. -Extended self-test routine -recommended polling time: ( 40) minutes. - -SMART Attributes Data Structure revision number: 11 -Vendor Specific SMART Attributes with Thresholds: -ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE WHEN_FAILED RAW_VALUE - 1 Raw_Read_Error_Rate 0x0029 100 253 020 Pre-fail - 0 - 3 Spin_Up_Time 0x0027 065 064 020 Pre-fail - 4481 - 4 Start_Stop_Count 0x0032 100 100 008 Old_age - 81 - 5 Reallocated_Sector_Ct 0x0033 100 100 020 Pre-fail - 0 - 7 Seek_Error_Rate 0x000b 100 100 023 Pre-fail - 0 - 9 Power_On_Hours 0x0012 098 098 001 Old_age - 1767 - 10 Spin_Retry_Count 0x0026 100 100 000 Old_age - 0 - 11 Calibration_Retry_Count 0x0013 100 100 020 Pre-fail - 0 - 12 Power_Cycle_Count 0x0032 100 100 008 Old_age - 81 - 13 Read_Soft_Error_Rate 0x000b 100 100 023 Pre-fail - 0 -194 Temperature_Centigrade 0x0022 091 084 042 Old_age - 24 -195 Hardware_ECC_Recovered 0x001a 100 100 000 Old_age - 52795 -196 Reallocated_Event_Count 0x0010 100 100 020 Old_age - 0 -197 Current_Pending_Sector 0x0032 100 100 020 Old_age - 0 -198 Offline_Uncorrectable 0x0010 100 253 000 Old_age - 0 -199 UDMA_CRC_Error_Count 0x001a 200 200 000 Old_age - 0 - -SMART Error Log Version: 1 -No Errors Logged - -SMART Self-test log, version number 1 -Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error -# 1 Extended off-line Completed 00% 1283 diff --git a/www/examples/MAXTOR-6.txt b/www/examples/MAXTOR-6.txt deleted file mode 100644 index fe37f6541..000000000 --- a/www/examples/MAXTOR-6.txt +++ /dev/null @@ -1,156 +0,0 @@ -# /usr/sbin/smartctl -a -m /dev/hda -smartctl version 5.0-49 Copyright (C) 2002 Bruce Allen -Home page is http://smartmontools.sourceforge.net/ - -=== START OF INFORMATION SECTION === -Device Model: Maxtor 4R080J0 -Serial Number: R20BZ3LE -Firmware Version: RAMB1TU0 -ATA Version is: 7 -ATA Standard is: Unrecognized. Minor revision code: 0x1e -SMART support is: Available - device has SMART capability. -SMART support is: Enabled - -=== START OF READ SMART DATA SECTION === -SMART overall-health self-assessment test result: PASSED - -General SMART Values: -Off-line data collection status: (0x82) Offline data collection activity - completed without error. -Self-test execution status: ( 33) The self-test routine was interrupted - by the host with a hard or soft reset. -Total time to complete off-line -data collection: ( 241) seconds. -Offline data collection -capabilities: (0x5b) SMART execute Offline immediate. - Automatic timer ON/OFF support. - Suspend Offline collection upon new - command. - Offline surface scan supported. - Self-test supported. -SMART capabilities: (0x0003) Saves SMART data before entering - power-saving mode. - Supports SMART auto save timer. -Error logging capability: (0x01) Error logging supported. -Short self-test routine -recommended polling time: ( 2) minutes. -Extended self-test routine -recommended polling time: ( 41) minutes. - -SMART Attributes Data Structure revision number: 16 -Vendor Specific SMART Attributes with Thresholds: -ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE WHEN_FAILED RAW_VALUE - 3 Spin_Up_Time 0x0027 252 252 063 Pre-fail - 1621 - 4 Start_Stop_Count 0x0032 253 253 000 Old_age - 18 - 5 Reallocated_Sector_Ct 0x0033 253 253 063 Pre-fail - 0 - 6 Read_Channel_Margin 0x0001 253 253 100 Pre-fail - 0 - 7 Seek_Error_Rate 0x000a 253 252 000 Old_age - 0 - 8 Seek_Time_Performance 0x0027 252 244 187 Pre-fail - 41642 - 9 Power_On_Hours 0x0032 253 253 000 Old_age - 27 h + 13 m - 10 Spin_Retry_Count 0x002b 252 252 157 Pre-fail - 0 - 11 Calibration_Retry_Count 0x002b 253 252 223 Pre-fail - 0 - 12 Power_Cycle_Count 0x0032 253 253 000 Old_age - 24 -192 Power-Off_Retract_Count 0x0032 253 253 000 Old_age - 0 -193 Load_Cycle_Count 0x0032 253 253 000 Old_age - 0 -194 Temperature_Celsius 0x0032 253 253 000 Old_age - 29 -195 Hardware_ECC_Recovered 0x000a 253 252 000 Old_age - 31004 -196 Reallocated_Event_Count 0x0008 253 253 000 Old_age - 0 -197 Current_Pending_Sector 0x0008 253 253 000 Old_age - 0 -198 Offline_Uncorrectable 0x0008 253 253 000 Old_age - 0 -199 UDMA_CRC_Error_Count 0x0008 199 199 000 Old_age - 0 -200 Multi_Zone_Error_Rate 0x000a 253 252 000 Old_age - 0 -201 Unknown_Attribute 0x000a 253 252 000 Old_age - 3 -202 Unknown_Attribute 0x000a 253 252 000 Old_age - 0 -203 Unknown_Attribute 0x000b 253 252 180 Pre-fail - 2 -204 Unknown_Attribute 0x000a 253 252 000 Old_age - 0 -205 Unknown_Attribute 0x000a 253 252 000 Old_age - 0 -207 Unknown_Attribute 0x002a 252 252 000 Old_age - 0 -208 Unknown_Attribute 0x002a 252 252 000 Old_age - 0 -209 Unknown_Attribute 0x0024 079 063 000 Old_age - 0 - 99 Unknown_Attribute 0x0004 253 253 000 Old_age - 0 -100 Unknown_Attribute 0x0004 253 253 000 Old_age - 0 -101 Unknown_Attribute 0x0004 253 253 000 Old_age - 0 - -SMART Error Log Version: 1 -ATA Error Count: 5 - DCR = Device Control Register - FR = Features Register - SC = Sector Count Register - SN = Sector Number Register - CL = Cylinder Low Register - CH = Cylinder High Register - D/H = Device/Head Register - CR = Content written to Command Register - ER = Error register - STA = Status register -Timestamp is seconds since the previous disk power-on. -Note: timestamp "wraps" after 2^32 msec = 49.710 days. - -Error 5 occurred at disk power-on lifetime: 4 hours -When the command that caused the error occurred, the device was in an unknown state. -After command completion occurred, registers were: -ER:04 SC:00 SN:00 CL:f4 CH:2c D/H:00 ST:01 -Sequence of commands leading to the command that caused the error were: -DCR FR SC SN CL CH D/H CR Timestamp - 0e d4 00 82 4f c2 f0 b0 8907.296 - 08 d4 00 82 4f c2 f0 b0 6260.832 - 08 d1 01 01 4f c2 f0 b0 6260.800 - 08 d0 01 00 4f c2 f0 b0 6260.768 - 08 da 00 00 4f c2 10 b0 6260.736 - -Error 4 occurred at disk power-on lifetime: 1 hours -When the command that caused the error occurred, the device was in an unknown state. -After command completion occurred, registers were: -ER:04 SC:00 SN:00 CL:f4 CH:2c D/H:00 ST:01 -Sequence of commands leading to the command that caused the error were: -DCR FR SC SN CL CH D/H CR Timestamp - 0e d4 00 82 4f c2 f0 b0 1944.192 - 08 d4 00 82 4f c2 f0 b0 1824.240 - 08 d1 01 01 4f c2 f0 b0 1824.224 - 08 d0 01 00 4f c2 f0 b0 1824.160 - 08 00 08 3f 00 00 f0 ca 1810.400 - -Error 3 occurred at disk power-on lifetime: 1 hours -When the command that caused the error occurred, the device was in an unknown state. -After command completion occurred, registers were: -ER:04 SC:00 SN:00 CL:f4 CH:2c D/H:00 ST:01 -Sequence of commands leading to the command that caused the error were: -DCR FR SC SN CL CH D/H CR Timestamp - 0e d4 00 82 4f c2 f0 b0 1456.432 - 08 d4 00 82 4f c2 f0 b0 1379.456 - 08 d1 01 01 4f c2 f0 b0 1379.440 - 08 d0 01 00 4f c2 f0 b0 1379.376 - 08 00 08 f7 01 54 f0 ca 1378.544 - -Error 2 occurred at disk power-on lifetime: 0 hours -When the command that caused the error occurred, the device was in an unknown state. -After command completion occurred, registers were: -ER:04 SC:00 SN:00 CL:f4 CH:2c D/H:00 ST:51 -Sequence of commands leading to the command that caused the error were: -DCR FR SC SN CL CH D/H CR Timestamp - 08 d4 00 82 4f c2 f0 b0 908.320 - 08 d1 01 01 4f c2 f0 b0 908.320 - 08 d0 01 00 4f c2 f0 b0 908.272 - 08 d4 00 7f 4f c2 f0 b0 905.696 - 08 d1 01 01 4f c2 f0 b0 905.664 - -Error 1 occurred at disk power-on lifetime: 0 hours -When the command that caused the error occurred, the device was in an unknown state. -After command completion occurred, registers were: -ER:04 SC:50 SN:40 CL:97 CH:03 D/H:10 ST:51 -Sequence of commands leading to the command that caused the error were: -DCR FR SC SN CL CH D/H CR Timestamp - 00 fe 00 00 00 00 10 ef 137.184 - 00 3d 00 00 00 00 10 c3 137.136 - 00 e4 00 00 00 00 10 c3 137.088 - 00 3d 00 00 00 00 10 c3 137.088 - 00 00 00 00 5e 20 10 70 137.040 - -SMART Self-test log, version number 1 -Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error -# 1 Extended captive Interrupted (host reset) 10% 4 -# 2 Short off-line Completed 00% 2 -# 3 Short captive Completed 00% 2 -# 4 Extended captive Interrupted (host reset) 40% 1 -# 5 Extended captive Interrupted (host reset) 70% 1 -# 6 Extended captive Interrupted (host reset) 40% 0 diff --git a/www/examples/Maxtor-5.txt b/www/examples/Maxtor-5.txt deleted file mode 100644 index 3bb171eb6..000000000 --- a/www/examples/Maxtor-5.txt +++ /dev/null @@ -1,127 +0,0 @@ -smartctl version 5.0-36 Copyright (C) 2002 Bruce Allen -Home page is http://smartmontools.sourceforge.net/ - -=== START OF INFORMATION SECTION === -Device Model: Maxtor 98196H8 -Serial Number: V80HV6NC -Firmware Version: ZAH814Y0 -ATA Version is: 6 -ATA Standard is: ATA/ATAPI-6 T13 1410D revision 0 -SMART support is: Available - device has SMART capability. -SMART support is: Enabled - -=== START OF READ SMART DATA SECTION === -SMART overall-health self-assessment test result: PASSED - -General SMART Values: -Off-line data collection status: (0x00) Offline data collection activity was - never started. -Self-test execution status: ( 0) The previous self-test routine completed - without error or no self-test has ever - been run. -Total time to complete off-line -data collection: ( 30) seconds. -Offline data collection -capabilities: (0x1b) SMART execute Offline immediate. - Automatic timer ON/OFF support. - Suspend Offline collection upon new - command. - Offline surface scan supported. - Self-test supported. -SMART capabilities: (0x0003) Saves SMART data before entering - power-saving mode. - Supports SMART auto save timer. -Error logging capability: (0x01) Error logging supported. -Short self-test routine -recommended polling time: ( 2) minutes. -Extended self-test routine -recommended polling time: ( 60) minutes. - -SMART Attributes Data Structure revision number: 16 -Vendor Specific SMART Attributes with Thresholds: -ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE WHEN_FAILED RAW_VALUE - 1 Raw_Read_Error_Rate 0x000a 253 252 000 Old_age - 26 - 3 Spin_Up_Time 0x0027 208 206 063 Pre-fail - 11285 - 4 Start_Stop_Count 0x0032 253 253 000 Old_age - 62 - 5 Reallocated_Sector_Ct 0x0033 253 253 063 Pre-fail - 0 - 6 Read_Channel_Margin 0x0001 253 253 100 Pre-fail - 0 - 7 Seek_Error_Rate 0x000a 253 252 000 Old_age - 0 - 8 Seek_Time_Performance 0x0027 249 244 187 Pre-fail - 50271 - 9 Power_On_Hours 0x0032 236 236 000 Old_age - 32671 - 10 Spin_Retry_Count 0x002b 253 252 223 Pre-fail - 0 - 11 Calibration_Retry_Count 0x002b 253 252 223 Pre-fail - 0 - 12 Power_Cycle_Count 0x0032 253 253 000 Old_age - 67 -196 Reallocated_Event_Count 0x0008 253 253 000 Old_age - 0 -197 Current_Pending_Sector 0x0008 253 253 000 Old_age - 0 -198 Offline_Uncorrectable 0x0008 253 253 000 Old_age - 0 -199 UDMA_CRC_Error_Count 0x0008 199 199 000 Old_age - 0 -200 Unknown_Attribute 0x000a 253 252 000 Old_age - 0 -201 Unknown_Attribute 0x000a 253 252 000 Old_age - 1 -202 Unknown_Attribute 0x000a 253 252 000 Old_age - 0 -203 Unknown_Attribute 0x000b 253 252 180 Pre-fail - 2 -204 Unknown_Attribute 0x000a 253 252 000 Old_age - 0 -205 Unknown_Attribute 0x000a 253 252 000 Old_age - 0 -207 Unknown_Attribute 0x002a 253 252 000 Old_age - 0 -208 Unknown_Attribute 0x002a 253 252 000 Old_age - 0 -209 Unknown_Attribute 0x0024 253 253 000 Old_age - 0 - 96 Unknown_Attribute 0x0004 253 253 000 Old_age - 0 - 97 Unknown_Attribute 0x0004 253 253 000 Old_age - 0 - 98 Unknown_Attribute 0x0004 253 253 000 Old_age - 0 - 99 Unknown_Attribute 0x0004 253 253 000 Old_age - 0 -100 Unknown_Attribute 0x0004 253 253 000 Old_age - 0 -101 Unknown_Attribute 0x0004 253 253 000 Old_age - 0 - -SMART Error Log Version: 1 -ATA Error Count: 3 - DCR = Device Control Register - FR = Features Register - SC = Sector Count Register - SN = Sector Number Register - CL = Cylinder Low Register - CH = Cylinder High Register - D/H = Device/Head Register - CR = Content written to Command Register - ER = Error register - STA = Status register -Timestamp is seconds since the previous disk power-on. -Note: timestamp "wraps" after 2^32 msec = 49.710 days. - -Error 1 occurred at disk power-on lifetime: 0 hours -When the command that caused the error occurred, the device was in an unknown state. -After command completion occurred, registers were: -ER:04 SC:40 SN:42 CL:97 CH:23 D/H:00 ST:51 -Sequence of commands leading to the command that caused the error were: -DCR FR SC SN CL CH D/H CR Timestamp - 00 fe 00 00 00 00 00 ef 137.440 - 00 d9 00 00 4f c2 00 b0 137.328 - 00 da 00 00 4f c2 00 b0 137.232 - 00 d8 00 00 4f c2 00 b0 137.152 - 00 db 00 00 4f c2 00 b0 136.976 - -Error 2 occurred at disk power-on lifetime: 0 hours -When the command that caused the error occurred, the device was in an unknown state. -After command completion occurred, registers were: -ER:04 SC:40 SN:40 CL:97 CH:23 D/H:00 ST:51 -Sequence of commands leading to the command that caused the error were: -DCR FR SC SN CL CH D/H CR Timestamp - 00 fe 00 00 00 00 00 ef 342.432 - 00 e4 00 00 00 00 00 c3 342.368 - 00 d0 00 00 0a 00 00 c3 342.368 - 00 fe 00 00 00 00 00 ef 342.304 - 00 3d 00 00 00 00 00 c3 342.256 - -Error 3 occurred at disk power-on lifetime: 0 hours -When the command that caused the error occurred, the device was in an unknown state. -After command completion occurred, registers were: -ER:04 SC:40 SN:40 CL:97 CH:03 D/H:00 ST:51 -Sequence of commands leading to the command that caused the error were: -DCR FR SC SN CL CH D/H CR Timestamp - 00 fe 00 00 00 00 00 ef 342.304 - 00 3d 00 00 00 00 00 c3 342.256 - 00 e4 00 00 00 00 00 c3 342.192 - 00 3d 00 00 00 00 00 c3 342.192 - 00 00 01 01 00 00 00 ec 342.144 - -SMART Self-test log, version number 1 -Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error -# 1 Short off-line Completed 00% 5255 diff --git a/www/examples/TOSHIBA-0.txt b/www/examples/TOSHIBA-0.txt deleted file mode 100644 index 965e55d99..000000000 --- a/www/examples/TOSHIBA-0.txt +++ /dev/null @@ -1,73 +0,0 @@ -smartctl version 5.0-31 Copyright (C) 2002 Bruce Allen -Home page is http://smartmontools.sourceforge.net/ - -=== START OF INFORMATION SECTION === -Device Model: TOSHIBA MK2018GAS -Serial Number: X22F7553T -Firmware Version: Q2.03 D -ATA Version is: 5 -ATA Standard is: Unrecognized. Minor revision code: 0x00 -SMART support is: Available - device has SMART capability. -SMART support is: Enabled - -=== START OF READ SMART DATA SECTION === -SMART overall-health self-assessment test result: PASSED - -General SMART Values: -Off-line data collection status: (0x00) Offline data collection activity was - never started. -Self-test execution status: ( 0) The previous self-test routine completed - without error or no self-test has ever - been run. -Total time to complete off-line -data collection: ( 212) seconds. -Offline data collection -capabilities: (0x1b) SMART execute Offline immediate. - Automatic timer ON/OFF support. - Suspend Offline collection upon new - command. - Offline surface scan supported. - Self-test supported. -SMART capabilities: (0x0003) Saves SMART data before entering - power-saving mode. - Supports SMART auto save timer. -Error logging capability: (0x01) Error logging supported. -Short self-test routine -recommended polling time: ( 2) minutes. -Extended self-test routine -recommended polling time: ( 23) minutes. - -SMART Attributes Data Structure revision number: 16 -Vendor Specific SMART Attributes with Thresholds: -ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE WHEN_FAILED RAW_VALUE - 1 Raw_Read_Error_Rate 0x000b 100 100 050 Pre-fail - 0 - 2 Throughput_Performance 0x0005 100 100 050 Pre-fail - 0 - 3 Spin_Up_Time 0x0027 100 100 001 Pre-fail - 910 - 4 Start_Stop_Count 0x0032 100 100 000 Old_age - 18 - 5 Reallocated_Sector_Ct 0x0033 100 100 050 Pre-fail - 0 - 7 Seek_Error_Rate 0x000b 100 100 050 Pre-fail - 0 - 8 Seek_Time_Performance 0x0005 100 100 050 Pre-fail - 0 - 9 Power_On_Hours 0x0032 100 100 000 Old_age - 9 - 10 Spin_Retry_Count 0x0033 100 100 030 Pre-fail - 0 - 12 Power_Cycle_Count 0x0032 100 100 000 Old_age - 18 -192 Power-Off_Retract_Count 0x0032 100 100 000 Old_age - 6 -193 Load_Cycle_Count 0x0032 100 100 000 Old_age - 437 -196 Reallocated_Event_Count 0x0032 100 100 000 Old_age - 0 -197 Current_Pending_Sector 0x0032 100 100 000 Old_age - 0 -198 Offline_Uncorrectable 0x0030 100 100 000 Old_age - 0 -199 UDMA_CRC_Error_Count 0x0032 200 200 000 Old_age - 0 -220 Disk_Shift 0x0002 100 100 000 Old_age - 4250 -222 Loaded_Hours 0x0032 100 100 000 Old_age - 4 -223 Load_Retry_Count 0x0032 100 100 000 Old_age - 0 -224 Load_Friction 0x0022 100 100 000 Old_age - 0 -226 Load-in_Time 0x0026 100 100 000 Old_age - 590 -240 Unknown_Attribute 0x0001 100 100 001 Pre-fail - 0 - -SMART Error Log Version: 1 -No Errors Logged - -SMART Self-test log, version number 1 -Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error -# 1 Extended off-line Completed 00% 4 -# 2 Short captive Completed 00% 0 -# 3 Short off-line Completed 00% 0 diff --git a/www/examples/TOSHIBA-MK6021GAS.txt b/www/examples/TOSHIBA-MK6021GAS.txt deleted file mode 100644 index 776cb3dce..000000000 --- a/www/examples/TOSHIBA-MK6021GAS.txt +++ /dev/null @@ -1,74 +0,0 @@ -smartctl version 5.1-7 Copyright (C) 2002 Bruce Allen -Home page is http://smartmontools.sourceforge.net/ - -=== START OF INFORMATION SECTION === -Device Model: TOSHIBA MK6021GAS -Serial Number: Y2MJ1530T -Firmware Version: GA023A -ATA Version is: 5 -ATA Standard is: Unrecognized. Minor revision code: 0x00 -Local Time is: Mon Feb 17 09:37:27 2003 CST -SMART support is: Available - device has SMART capability. -SMART support is: Enabled - -=== START OF READ SMART DATA SECTION === -SMART overall-health self-assessment test result: PASSED - -General SMART Values: -Off-line data collection status: (0x00) Offline data collection activity was - never started. -Self-test execution status: ( 0) The previous self-test routine completed - without error or no self-test has ever - been run. -Total time to complete off-line -data collection: ( 587) seconds. -Offline data collection -capabilities: (0x1b) SMART execute Offline immediate. - Automatic timer ON/OFF support. - Suspend Offline collection upon new - command. - Offline surface scan supported. - Self-test supported. -SMART capabilities: (0x0003) Saves SMART data before entering - power-saving mode. - Supports SMART auto save timer. -Error logging capability: (0x01) Error logging supported. -Short self-test routine -recommended polling time: ( 2) minutes. -Extended self-test routine -recommended polling time: ( 65) minutes. - -SMART Attributes Data Structure revision number: 16 -Vendor Specific SMART Attributes with Thresholds: -ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE WHEN_FAILED RAW_VALUE - 1 Raw_Read_Error_Rate 0x000b 100 100 050 Pre-fail - 0 - 2 Throughput_Performance 0x0005 100 100 050 Pre-fail - 0 - 3 Spin_Up_Time 0x0027 100 100 001 Pre-fail - 1267 - 4 Start_Stop_Count 0x0032 100 100 000 Old_age - 18 - 5 Reallocated_Sector_Ct 0x0033 100 100 050 Pre-fail - 0 - 7 Seek_Error_Rate 0x000b 100 100 050 Pre-fail - 0 - 8 Seek_Time_Performance 0x0005 100 100 050 Pre-fail - 0 - 9 Power_On_Hours 0x0032 100 100 000 Old_age - 39 - 10 Spin_Retry_Count 0x0033 100 100 030 Pre-fail - 0 - 12 Power_Cycle_Count 0x0032 100 100 000 Old_age - 16 -192 Power-Off_Retract_Count 0x0032 100 100 000 Old_age - 1 -193 Load_Cycle_Count 0x0032 100 100 000 Old_age - 460 -194 Temperature_Celsius 0x0022 100 100 000 Old_age - 40 (Lifetime Min/Max 17/51) -196 Reallocated_Event_Count 0x0032 100 100 000 Old_age - 0 -197 Current_Pending_Sector 0x0032 100 100 000 Old_age - 0 -198 Offline_Uncorrectable 0x0030 100 100 000 Old_age - 0 -199 UDMA_CRC_Error_Count 0x0032 200 200 000 Old_age - 0 -220 Disk_Shift 0x0002 100 100 000 Old_age - 8332 -222 Loaded_Hours 0x0032 100 100 000 Old_age - 30 -223 Load_Retry_Count 0x0032 100 100 000 Old_age - 0 -224 Load_Friction 0x0022 100 100 000 Old_age - 0 -226 Load-in_Time 0x0026 100 100 000 Old_age - 159 -240 Head flying hours 0x0001 100 100 001 Pre-fail - 0 - -SMART Error Log Version: 1 -No Errors Logged - -SMART Self-test log, version number 1 -Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error -# 1 Extended off-line Completed 00% 4 - - diff --git a/www/index.html b/www/index.html deleted file mode 100644 index cb191ad0e..000000000 --- a/www/index.html +++ /dev/null @@ -1,467 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> -<head> - <title>smartmontools Home Page</title> - <link rev="made" href="mailto:smartmontools-support@sourceforge.net" /> - <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /> - <meta name="description" content="smartmontools Home Page" /> - <meta name="keywords" content="SMART, S.M.A.R.T., Linux, disk monitoring" /> -</head> -<body> - -<div align="center"><h1><font color="#3333ff">smartmontools Home Page</font></h1></div> - -<p>This is the home page for smartmontools.  The smartmontools -package contains two utility programs -(<font color="#3333ff"><b>smartctl</b></font> and -<font color="#3333ff"><b>smartd</b></font>) to control and monitor storage -systems using the Self-Monitoring, Analysis and Reporting Technology -System (S.M.A.R.T.) built into most modern ATA and SCSI hard -disks.  It is derived from the smartsuite package, and includes -support for ATA/ATAPI-5 disks.  It should run on any modern Linux -system.</p> - -<p>For printing convenience, everything except for the <a href="#sampleoutput">example output</a> is on a single page.</p> - -<hr size="2" /> - -<ul> -<li><a href="#howtodownload">How to download and install -smartmontools</a></li> -<li><a href="#PROBLEMS">Serious Problem Reports (system lockup, etc.)</a></li> -<li><a href="#FAQ">Frequently Asked Questions</a></li> -<li><a href="#testinghelp">The code needs to be tested on SCSI, -FireWire, USB, and SATA disks/tapes</a></li> -<li><a href="#differfromsmartsuite">How does smartmontools differ from -smartsuite?</a></li> -<li><a href="#references">Useful references on S.M.A.R.T. and -ATA/ATAPI-5, -6, and -7</a></li> -<li><a href="#sampleoutput">Example output from smartmontools</a> -<b>smartctl</b> utility</li> -<li><a href="http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/smartmontools/">CVS -repository</a> and <a href="http://sourceforge.net/projects/smartmontools/">SourceForge's -Project Page</a></li> -<li>Mailing List <a href="http://lists.sourceforge.net/lists/listinfo/smartmontools-support">Information</a> -and <a href="http://sourceforge.net/mailarchive/forum.php?forum=smartmontools-support">Archives</a></li> -</ul> - -<hr size="2" /> - -<b><a name="howtodownload"></a>How to download and install -smartmontools</b> - -<p>There are four different ways to get and install -smartmontools.  You can use any of the first three procedures -(the fourth is for Debian only).  Just after "Method 4" below are -some instructions for trying out smartmontools once you have completed -the installation.</p> - -<b>First Method - Install from the RPM file</b> -<ul> -<li>Download the latest binary RPM file (<tt>*.rpm</tt>) from <a href="http://sourceforge.net/project/showfiles.php?group_id=64297">here</a>.  -Don't get the SRPM file (<tt>*.src.rpm</tt>).</li> -<li>Install it using RPM.  <i>You must be root to do this</i>: -<pre>su root (enter root password) -rpm -ivh smartmontools-5.0-1.i386.rpm</pre> -For most users, this is all that is needed.</li> -<li>If you receive an error message, you have probably previously -installed the <tt>smartsuite</tt> package, or RedHat's -<tt>kernel-utils</tt> package, which provide older versions of the -<tt>smartd</tt> and <tt>smartctl</tt> utilities.  In this case you -should use the <tt>--nodeps</tt> or <tt>--force</tt> arguments of rpm to -replace these two utilities: -<pre>rpm -ivh --nodeps --force smartmontools-5.0-1.i386.rpm</pre></li> -<li>If you want to remove the package (<tt>rpm -e smartmontools</tt>) -and your system does not have <tt>chkconfig</tt> installed, you may need -to use: -<pre>rpm -e --noscripts smartmontools</pre></li> -</ul> - -<b>Second Method - Install from the source tarball</b> -<ul> -<li>Download the latest source tarball from <a href="http://sourceforge.net/project/showfiles.php?group_id=64297">here</a>. -Note: you probably want the most recent release.</li> -<li>Uncompress the tarball: -<pre>tar zxvf smartmontools-5.0-1.tar.gz</pre></li> -<li>The previous step created a directory called smartmontools-5.0-1 -containing the code.  Go to that directory, build, and install: -<pre>cd smartmontools-5.0-1 -make -make install (only root can do this)</pre></li> -</ul> - -<b>Third Method - Install from the CVS repository</b> -<ul> -<li><p>One of the really cool things about CVS is that you can get -<i>any</i> version of the code you want, from the first release up the -the most current development version.  And it's trivial, because -each release is <u>tagged</u> with a name like -<tt>RELEASE_5_0_26</tt>.  You can see what the different names are -by looking at the <a href="http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/smartmontools/sm5/"> -CVS repository</a>.  You'll see the tag names in the little scroll -window where it says "Show only files with tag".  All you need to -do to get the latest development code is -(but note that the development code may be unstable, and that the -documentation and code may be inconsistent):</p> - -<pre>cvs -d:pserver:anonymous@cvs.smartmontools.sourceforge.net:/cvsroot/smartmontools login (when prompted for a password, just press Enter) -cvs -d:pserver:anonymous@cvs.smartmontools.sourceforge.net:/cvsroot/smartmontools co sm5</pre></li> - -<li>To instead get the 5.0-26 release: - -<pre>cvs -d:pserver:anonymous@cvs.smartmontools.sourceforge.net:/cvsroot/smartmontools co -r RELEASE_5_0_26 sm5</pre></li> - -<li><p>This will create a subdirectory called <tt>sm5/</tt> containing the -code.  Go to that directory, build, and install:</p> - -<pre>cd sm5 -make -make install (only root can do this)</pre></li> - -<li>To update your sources to the 5.0-30 release: - -<pre>cd sm5 -cvs up -r RELEASE_5_0_30</pre></li> - -<li>To update any tagged release to the latest development code: - -<pre>cd sm5 -cvs up -A</pre></li> -</ul> - -<b>Fourth Method - Install the Debian package (for machines using the Debian linux distribution)</b> -<ul> -<li> -The latest version of the smartmontools package in <i>.deb</i> format is -available at the <a href="http://packages.debian.org/unstable/utils/smartmontools.html">Debian smartmontools -package page</a>. -This package is for the (unreleased) <a href="http://www.debian.org/releases/">unstable</a> -distribution.</li> -<li>If you're running Debian <a -href="http://www.debian.org/releases/stable/">stable</a> please download the -package from <a -href="http://honk.physik.uni-konstanz.de/~agx/linux-i386/debian/smartmontools/">here</a>.</li> -<li> -You can then install the package using: -<pre> -dpkg -i smartmontools_5.1.4-2.agx0_i386.deb -</pre> -But the preferred method is to add the following line to your -<tt>/etc/apt/sources.list</tt>: -<pre>deb http://honk.physik.uni-konstanz.de/~agx/linux-i386/debian smartmontools/ -</pre> -and type <pre> -apt-get update && apt-get install smartmontools -</pre> this will automatically download and install the package. -</li> -</ul> - -<b>After installing smartmontools using Method 1, 2, 3 or 4 above, you can read the man -pages, and try out the commands:</b> - -<pre>man 8 smartctl -man 8 smartd -/usr/sbin/smartctl -s on -o on -S on /dev/hda (only root can do this) -/usr/sbin/smartctl -a /dev/hda (only root can do this)</pre> - -<p>Note that the default location for the manual pages are in -<tt>/usr/share/man/man8</tt>.  If "<tt>man</tt>" does not find the -manual pages, then you may need to add <tt>/usr/share/man</tt> to your -<tt>MANPATH</tt> environment variable.</p> - -<hr size="2" /> - -<a name="PROBLEMS"></a><b>Serious Problem Reports</b> -<p>If a serious problem gets reported to us, it gets added to the <a -href="http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/smartmontools/sm5/WARNINGS?rev=HEAD&content-type=text/vnd.viewcvs-markup"> -WARNINGS</a> file in smartmontools. So far there are only two problem systems listed.</p> - -<a name="FAQ"></a><b>Frequently Asked Questions</b> - -<p>If your question is not here, please <a href="mailto:smartmontools-support@lists.sourceforge.net">email -me</a>.</p> - -<ul> -<li><b>What do I do if I have problems, or need support?  Suppose -I want to become a developer, or suggest some new extensions?</b> - -<p>Please send an email to the <a href="http://lists.sourceforge.net/mailman/listinfo/smartmontools-support">smartmontools-support -mailing list</a>.  Please take a look through the archives to see -if your question has been answered.</p></li> - -<li><b>What are the future plans for smartmontools?</b> - -<p>My plan is that smartmontools-5.x will support ATA/ATAPI-5 -disks.  Eventually, we'll do smartmontools-6.x to support -ATA/ATAPI-6 disks, smartmontools-7.x for the ATA/ATAPI-7 standard, and -so on.  The "x" will denote revision level, as bugs get found and -fixed, and as enhancements get added.  If it's possible to maintain -backwards compatibility, that would be nice, but I don't know if it will -be possible or practical.</p></li> - -<li><b>Why are you doing this?</b> - -<p>My research group at U. Wisconsin - Milwaukee runs a <a -href="http:www.lsc-group.phys.uwm.edu/beowulf/medusa">beowulf -cluster</a> with 600 ATA-5 and -6 disks (300 IBM and 300 -Maxtor).  We have more than 50 TB of data stored on the -system.  I also help out with a <a -href="http://pandora.aei.mpg.de/merlin/"> cluster</a> at the Albert -Einstein Institute that has another 300 IBM ATA-6 disks (36 TB -total). It's nice to have advanced warning when a disk is going to -fail.</p></li> - -<li><b>I see some strange output from smartctl. What does it mean?</b> - -<p>The raw S.M.A.R.T. attributes (temperature, power-on lifetime, and so -on) are stored in vendor-specific structures.  Sometime these are -strange.  Hitachi disks (at least some of them) store power-on -lifetime in minutes, rather than hours (see next question below).  IBM disks (at least some -of them) have three temperatures stored in the raw structure, not just -one.  And so on.  If you find strange output, or unknown -attributes, please send an email to <a href="http://lists.sourceforge.net/mailman/listinfo/smartmontools-support"> -smartmontools-support</a> and we'll help you try and figure it -out.</p></li> - -<li><b>My Maxtor/Hitachi disk is only a few days old, yet smartctl reports its age (Attribute 9) as thousands of hours!</b> - -<p>On some recent disks, Maxtor has started to use Attribute 9 to -store the lifetime in minutes rather than hours. In this case, use -the -m option (smartctl versions 5.0.X) or the ---vendorattribute=9,minutes (smartctl 5.1.X) option to correctly -display hours and minutes. -</p></li> - -<li><b>What Kernel Version is needed?</b> - -<p> -Unfortunately I can't give a definitive answer to this question. In -principle the 2.4 series kernels all provide the needed support. The -later 2.2 series kernels should work OK. However, depending upon the -2.2 kernel version, patch level, and configuration options, they may -not support the HDIO_DRIVE_TASK ioctl(). This is needed for the drive -to execute the ATA SMART RETURN STATUS command. -</p></li> - -<li><b>What attributes does smartmontools not yet recognize?</b> - -<p>From a Hitachi disk: (250). From -Maxtor disks (99), (100), (101), (201), (202), (203), (204), (205), (207), (208), (209). -</p> - -<p>If you can attach names/meanings to these attributes, please send a -note to <a -href="http://lists.sourceforge.net/mailman/listinfo/smartmontools-support"> -smartmontools-support</a>. If you have access to other -S.M.A.R.T. utilities (especially manufacturer-specific ones, see -below) and can send us comparison output from smartctl and the other -utility, that's especially useful.</p></li> - - -<li><b>Where can I find manufacturer-specific disk-testing utilities?</b> - -<p>A good listing of such utilities can be found <a -href="http://www.benchmarkhq.ru/english.html?/be_hdd2.html">here</a>. -Unfortunately most of these are for MS operating systems. If you do -run one of these utilities, and it identifies the meanings of any -SMART Attributes that are not known to smartmontools, please report -them to the mailing list above.</p></li> - -<li><b>When I run <tt>smartd</tt>, the SYSLOG <tt>/var/log/messages</tt> -contains messages like this:</b> -<pre>smartd: Reading Device /dev/sdv -modprobe: modprobe: Can't locate module block-major-65</pre> - -<p>This is because when <tt>smartd</tt> starts, it looks for all ATA and -SCSI devices to monitor (matching the pattern <tt>/dev/hd[a-z]</tt> or -<tt>/dev/sd[a-z]</tt>).  The log messages appear because your -system doesn't have most of these devices.</p> - -<p>Recent releases of smartd can use a configuration file -<tt>/etc/smartd.conf</tt> to specify which devices to include or exclude -from start-up search.</p></li> - -<li><b>What's the story on IBM S.M.A.R.T. disks?</b> - -<p>Apparently some of the older S.M.A.R.T. firmware on IBM disks can -interfere with the regular operation of the disk.  If you have this -problem, here is an <a href="http://www.geocities.com/dtla_update/">IBM -DISK FIRMWARE UPGRADE</a> that fixes the problem. -</p></li> -</ul> - -<hr size="2" /><a name="testinghelp"></a><b>Help needed in testing -smartmontools, especially on SCSI, FireWire, USB, and SATA disks/systems</b> -<p>I have access to a number of systems with ATA S.M.A.R.T. disks, but -I don't have any access to systems with SCSI, FireWire, USB, and SATA -S.M.A.R.T. devices. <br /> -</p> -<p>Work on smartmontools support for SCSI disks and SCSI tape drives -(TapeAlerts) is progressing. See this <a - href="http://www.torque.net/scsi/smartmontools_scsi.html">article</a> -for more details and examples. Do you have a beowulf cluster with a few -hundred SCSI disks and tape jukeboxes? We are looking for testers.</p> -<p>A package of SCSI utilities including one to examine SCSI log -information can be found on the <a href="http://www.torque.net/sg/">scsi -generic (sg) driver home page</a>. The package is called <tt>sg3_utils</tt>.<br /> -</p> -<p>As for USB and FireWire (ieee1394) disks and tape drives, the news -is not good. They appear to Linux as SCSI devices but their -implementations do not usually support those commands needed for -S.M.A.R.T. support. The ieee1394 consortium recently certified the <span - style="font-style: italic;">first</span> external enclosure (containing -a ATA disk and a protocol bridge) as being compliant to the relevant -standards. Such devices have been on the market for about 3 years!<br /> -</p> -<p>I'd be very grateful to find someone who could help me test the -smartmontools code on serial ATA (SATA) disks. They should appear as -normal ATA disks in Linux.</p> - -<hr size="2" /><a name="differfromsmartsuite"></a><b>How does -smartmontools differ from smartsuite?</b> - -<p>The smartsuite code was originally developed as a Senior Thesis by -Michael Cornwell at the Concurrent Systems Laboratory (now part of the -<a href="http://ssrc.soe.ucsc.edu/">Storage Systems Research -Center</a>), Jack Baskin School of Engineering, University of -California, Santa Cruz. -You can find some information about the original smartsuite project here: -<a href="http://www.ucsc.edu/news_events/press_releases/archive/99-00/09-99/smart_software.htm">Press Release 1</a>, -<a href="http://www.santa-cruz.com/archive/1999/September/22/local/stories/5local.htm">Press Release 2</a>, -<a href="http://www.ucsc.edu/currents/99-00/09-27/smart.html">Press Release 3</a>. -</p> - -<p>Smartmontools was derived directly from smartsuite.  It differs -from smartsuite in that it supports the ATA/ATAPI-5 standard.  So -for example <tt>smartctl</tt> from smartsuite has no facility for -printing the S.M.A.R.T. self-test logs, and doesn't print timestamp -information in the most usable way.  The <tt>smartctl</tt> utility -in smartmontools has added functionality for this (<tt>-q, -l selftest,-S, --T, -v and -m</tt> options), updated documentation, and also fixes small -technical bugs in smartsuite. [One example: smartsuite does not actually use the -ATA SMART RETURN STATUS command to find out the health status of a disk. It instead tries to infer this from the -SMART Attribute values.]  See the -<a href="http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/smartmontools/sm5/CHANGELOG?rev=HEAD&content-type=text/plain">CHANGELOG</a> -file in CVS for a summary of what's been done.  The <tt>smartd</tt> -utility differs from the smartsuite <tt>smartd</tt> in major ways.  -First, it prints somewhat more informative error messages to the syslog. -  Second, on startup it looks for a configuration file -<tt>/etc/smartd.conf</tt>, and if <tt>smartd</tt> finds this file, it -monitors the list of devices therein, rather than querying all IDE and -SCSI devices on your system.  (If the configuration file does not -exist, then it does query all IDE and SCSI devices.)  Also, it's -a well-behaved daemon and doesn't leave open file descriptors and other -detrius behind.  In addition, the <tt>smartmontools</tt> version of -<tt>smartd</tt> can be instructed (via Directives in the configuration -file) to monitor for changes in a number of different disk properties: -the SMART status, failure or prefailure attributes going below -threshold, new errors appearing in the ATA Error Log or the SMART -Self-Test Log, and so on. <tt>smartd</tt> can also send an email warning or run a -user-specified executable if it detects a problem with the disk. -</p> - -<p>The other principle difference is that smartmontools is an OpenSource -development project, meaning that we keep the files in CVS, and that -other developers who wish to contribute can commit changes to the -archive.  If you would like to contribute, please write to to <a href="http://lists.sourceforge.net/mailman/listinfo/smartmontools-support">smartmontools-support</a>.</p> - -<p>But the bottom line is that the code in smartmontools is derived -directly from smartsuite and is similar.  The smartsuite package -can be found <a href="http://sourceforge.net/projects/smartsuite/">here</a>.</p> - -<hr size="2" /><a name="references"></a><b><big>Useful references on -S.M.A.R.T. and the ATA/ATAPI standards</big></b> - -<p><big>If you are having trouble understanding the output of smartctl -or smartd, please first read the manual pages:</big></p> - -<pre> -man 8 smartctl -man 8 smartd -</pre> - -<p><big>If you'd like to know more about S.M.A.R.T., then the following -references may be helpful:</big></p> - -<ul> - <li>The <a href="http://www.t13.org/project/d1321r1c.pdf"> ATAPI/ATA-5 -Revision 1 specification</a> (start with Section 8.41)</li> - <li>The <a href="http://www.t13.org/docs2002/d1410r3b.pdf"> ATAPI/ATA-6 -Revision 3b specification</a></li> - <li>The ATAPI/ATA-7 -specification (Draft 2a) <a href="http://www.t13.org/docs2003/d1532v1r2a.pdf">Volume 1</a>, - <a href="http://www.t13.org/docs2003/d1532v2r2a.pdf">Volume 2</a>, - <a href="http://www.t13.org/docs2003/d1532v3r2a.pdf">Volume 3</a></li> - <li><a href="http://www.t13.org/#FTP_site">Earlier revisions -of the ATAPI/ATA Specs</a></li> -<li>SCSI References: -<ul> - <li>The <a href="http://www.t10.org">homepage of the T10 project</a>.</li> - <li>The <a href="ftp://ftp.t10.org/t10/drafts/s2/">SCSI-2 draft</a> by the T10 project.</li> - <li>See also other subdirectories <a href="ftp://ftp.t10.org/t10/drafts/">here</a>.</li> -</ul> -</li> -<li>The original S.M.A.R.T. specification is SFF-8035i from the <a href="http://www.sffcommittee.com/ns/">SFF Committee</a>.  -Here is their <a href="ftp://ftp.seagate.com/sff/INF-8035.TXT"> "link"</a>. -Revision 1 of the SFF-8035i document can be purchased from <a href="http://global.ihs.com/">Global Engineering Documents</a>. -Enter "SFF 8035i" in the "DOCUMENT NUMBER" search box in the top left corner. -</li> - <li>From the <a href="http://cmrr.ucsd.edu/smart/">UCSD SMART Project</a>: - <ul> - <li><a href="http://cmrr.ucsd.edu/smart/tech_papr/HamerlySmartPaper.pdf">Bayesian -Approaches to Failure Prediction for Disk Drives</a></li> - <li><a href="http://cmrr.ucsd.edu/smart/tech_papr/SmtPapTransReliFinalWeb.pdf">Improved -Disk-Drive Failure Warnings</a></li> - </ul> - </li> - <li>From the Seagate Corporation: - <ul> - <li><a href="http://www.seagate.com/docs/pdf/whitepaper/drive_reliability.pdf" target="_blank">Estimating Drive Reliability in Desktop Computers and -Consumer Electronics Systems</a></li> - <li><a href="http://www.seagate.com/docs/pdf/whitepaper/enhanced_smart.pdf" target="_blank">Enhanced SMART - Get S.M.A.R.T. For Reliability</a></li> - <li><a href="http://www.seagate.com/docs/pdf/whitepaper/smart_u8.pdf" target="_blank">Playing it S.M.A.R.T.</a></li> - <li><a href="http://www.seagate.com/docs/pdf/whitepaper/Enhanced_DST_Tech_Paper.pdf" target="_blank">Enhanced Drive Self-Test</a></li> - </ul> - </li> - <li><a href="http://www.maxtor.com/products/DiamondMax/software/maxsafe.pdf" target="_blank">Drive reliability and safety system: MaxSafe</a> (Maxtor)</li> - <li><u>Specifying Reliability in the Disk Drive Industry: No More -MTBF's</u>, Jon G. Elerath (IBM Storage Systems Division) in -<i>Proceedings of the IEEE 2000 Annual Reliability and Maintainability -Symposium, pg 194, 0-7803-5848-1/00/$10.00.</i></li> -</ul> - -<hr size="2" /><a name="sampleoutput"></a><b>Example output -from smartmontools smartctl utility:</b> - -<ul> - <li><a href="examples/MAXTOR-0.txt">MAXTOR 4K080H4</a> 80 GB 5400 RPM</li> - <li><a href="examples/MAXTOR-1.txt">MAXTOR 4K080H4</a> 80 GB 5400 RPM (has failing SMART status)</li> - <li><a href="examples/MAXTOR-2.txt">MAXTOR 4K080H4</a> 80 GB 5400 RPM (has had failing SMART test in the past. Look at the Seek Error Rate)</li> - <li><a href="examples/MAXTOR-3.txt">MAXTOR 6L080J4</a> 80 GB 7200 RPM</li> - <li><a href="examples/MAXTOR-4.txt">MAXTOR 6L080J4</a> 80 GB 7200 RPM</li> - <li><a href="examples/Maxtor-5.txt">Maxtor 98196H8</a> 80 GB 5400 RPM</li> - <li><a href="examples/MAXTOR-6.txt">Maxtor 4R080J0</a> Note: Attribute 9 (lifetime) stored in minutes!</li> - <li><a href="examples/IC35L120AVVA07-0-0.txt">IBM IC35L120AVVA07 (GXP 120 series)</a> 120 GB 7200 RPM (note 3 temperatures)</li> - <li><a href="examples/IC35L120AVVA07-0-1.txt">IBM IC35L120AVVA07 (GXP 120 series)</a> 120 GB 7200 RPM (note 3 temperatures)</li> - <li><a href="examples/IC35L120AVV207-0.txt">IBM IC35L120AVV207 (GXP 180 series)</a> 120 GB 7200 RPM (note 3 temperatures)</li> - <li><a href="examples/HITACHI_DK23BA-20-0.txt">HITACHI_DK23BA-20</a> Hitachi 20 GB Laptop Disk</li> - <li><a href="examples/TOSHIBA-0.txt">TOSHIBA MK2018GAS</a> Toshiba 20 GB Laptop Disk</li> - <li><a href="examples/TOSHIBA-MK6021GAS.txt">TOSHIBA MK6021GAS</a> Toshiba 60 GB Laptop Disk (note 3 temperatures)</li> -</ul> - -<hr size="2" /> - -Maintained by <a href="mailto:smartmontools-support@lists.sourceforge.net">Bruce Allen</a> - -<br /> - -<div align="center">Hosted by</div> - -<div align="center"><a href="http://sourceforge.net/"><img style="border:0;width=:88px;height:31px" src="http://sourceforge.net/sflogo.php?group_id=64297&type=5" alt="SourceForge.net" /></a></div> - -<br /> - -<div align="center"><a href="http://validator.w3.org/check/referer"><img style="border:0;width=:88px;height:31px" src="http://www.w3.org/Icons/valid-xhtml10.png" alt="Valid XHTML 1.0!" /></a></div> - -</body> -</html> diff --git a/www/script b/www/script deleted file mode 100755 index fa7cd8c22..000000000 --- a/www/script +++ /dev/null @@ -1,24 +0,0 @@ -#! /bin/bash - -# This is a script to wrap smartctl output into http:// displayable form -# It requires a filename as input, and produces an file with a .html extension as output - -if [ $# -ne 1 ] ; then - echo This script requires one a file as input - exit 1 -fi - -model=`grep "Device Model" $1 | awk '{print $3}' ` - -# see if file name in use -let i=0 -while [ -f $model-$i.html ] ; do - let i+=1 -done - -filename=$model-$i -echo -e "<pre><tt>\n" > $filename.html -cat $1 >> $filename.html -echo -e "</tt></pre>\n" >> $filename.html - -echo created file $filename.html -- GitLab