Skip to content
Snippets Groups Projects
Commit aad52673 authored by (no author)'s avatar (no author)
Browse files

This commit was manufactured by cvs2svn to create tag

'RELEASE_5_0_9'.

git-svn-id: https://smartmontools.svn.sourceforge.net/svnroot/smartmontools/tags/RELEASE_5_0_9@56 4ea69e1a-61f1-4043-bf83-b5c94c648137
parent c80bf8c9
Branches
Tags v1.2
No related merge requests found
# 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 '#'
# 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".
# 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
# 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'
# 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.
# 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
# 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.
# 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"
# 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".
# 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".
# 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.
// $Id: atacmds.cpp,v 1.8 2002/10/15 14:24:26 ballen4705 Exp $
/*
* atacmds.c
*
* Home page of code is: http://smartmontools.sourceforge.net
*
* Copyright (C) 2002 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 "atacmds.h"
// These Drive Identity tables are taken from hdparm 5.2. That's the
// "Gold Standard"
#define NOVAL_0 0x0000
#define NOVAL_1 0xffff
/* word 81: minor version number */
#define MINOR_MAX 0x1C
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 */
"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 */
"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 */
"Reserved", /* 0x001a */
"ATA/ATAPI-6 T13 1410D revision 2", /* 0x001b */
"ATA/ATAPI-6 T13 1410D revision 1", /* 0x001c */
"reserved" /* 0x001d */
"reserved" /* 0x001e */
"reserved" /* 0x001f-0xfffe*/
};
const char 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: */
0, /* 0x001a WARNING: */
6, /* 0x001b WARNING: */
6, /* 0x001c WARNING: */
0 /* 0x001d-0xfffe */
};
int ataReadHDIdentity ( int device, struct hd_driveid *buf)
{
if (ioctl ( device , HDIO_GET_IDENTITY, buf ) != 0)
{
perror ("ATA GET HD Failed");
return -1;
}
return 0;
}
int ataVersionInfo (const char** description, struct hd_driveid drive){
unsigned short major,minor;
int i,atavalue=0;
// 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=1; i<16;i++ )
if (major & (0x1<<i))
atavalue = i;
*description=NULL;
return atavalue;
}
int ataSmartSupport ( struct hd_driveid drive){
#ifdef __NEW_HD_DRIVE_ID
if (drive.command_set_1 & 0x0001)
#else
if (drive.command_sets & 0x0001)
#endif
return 1; /* drive supports S.M.A.R.T. and is disabled */
return 0;
}
int ataReadSmartValues (int device, struct ata_smart_values *data){
int i;
unsigned char chksum=0;
unsigned char buf[HDIO_DRIVE_CMD_HDR_SIZE+ATA_SMART_SEC_SIZE]=
{WIN_SMART, 0, SMART_READ_VALUES, 1};
if (ioctl(device,HDIO_DRIVE_CMD,buf)){
perror ("Smart Values Read failed");
return -1;
}
// compute checksum
for (i=0;i<ATA_SMART_SEC_SIZE;i++)
chksum+=buf[i+HDIO_DRIVE_CMD_HDR_SIZE];
// verify that checksum vanishes
if (chksum){
perror ("Smart Read Failed, Checksum error!");
return -1;
}
// copy data and return
memcpy(data,buf+HDIO_DRIVE_CMD_HDR_SIZE,ATA_SMART_SEC_SIZE);
return 0;
}
int ataReadSelfTestLog (int device, struct ata_smart_selftestlog *data)
{
int i;
unsigned char chksum=0;
unsigned char buf[ HDIO_DRIVE_CMD_HDR_SIZE +
ATA_SMART_SEC_SIZE] =
{ WIN_SMART, 0x06, SMART_READ_LOG_SECTOR, 1};
if (ioctl ( device , HDIO_DRIVE_CMD, (unsigned char *) &buf ) != 0)
{
perror ("Smart Error Log Read failed");
return -1;
}
// compute checksum
for (i=0;i<ATA_SMART_SEC_SIZE;i++)
chksum+=buf[HDIO_DRIVE_CMD_HDR_SIZE+i];
if (chksum){
fprintf(stderr,"Smart Self Test Log Checksum Incorrect!\n");
return -1;
}
memcpy( data, &buf[HDIO_DRIVE_CMD_HDR_SIZE] , ATA_SMART_SEC_SIZE);
return 0;
}
int ataReadErrorLog (int device, struct ata_smart_errorlog *data)
{
int i;
unsigned char chksum=0;
unsigned char buf[ HDIO_DRIVE_CMD_HDR_SIZE +
ATA_SMART_SEC_SIZE] =
{ WIN_SMART, 0x01, SMART_READ_LOG_SECTOR, 1};
if (ioctl ( device , HDIO_DRIVE_CMD, (unsigned char *) &buf ) != 0)
{
perror ("Smart Error Log Read failed");
return -1;
}
// compute checksum
for (i=0;i<ATA_SMART_SEC_SIZE;i++)
chksum+=buf[HDIO_DRIVE_CMD_HDR_SIZE+i];
if (chksum){
fprintf(stderr,"Smart Error Log Checksum Incorrect!\n");
return -1;
}
memcpy( data, &buf[HDIO_DRIVE_CMD_HDR_SIZE] , ATA_SMART_SEC_SIZE);
return 0;
}
int ataReadSmartThresholds ( int device, struct ata_smart_thresholds *data)
{
unsigned char buf[ HDIO_DRIVE_CMD_HDR_SIZE +
ATA_SMART_SEC_SIZE] =
{ WIN_SMART, 1, SMART_READ_THRESHOLDS, 1};
if (ioctl ( device , HDIO_DRIVE_CMD, (unsigned char *) &buf ) != 0)
{
perror ("Smart Thresholds Read failed");
return -1;
}
memcpy( data, &buf[HDIO_DRIVE_CMD_HDR_SIZE] , ATA_SMART_SEC_SIZE);
return 0;
}
int ataSetSmartThresholds ( int device, struct ata_smart_thresholds *data)
{
unsigned char buf[ HDIO_DRIVE_CMD_HDR_SIZE +
ATA_SMART_SEC_SIZE] =
{ WIN_SMART, 1, 0xD7, 1};
memcpy( &buf[HDIO_DRIVE_CMD_HDR_SIZE], data , ATA_SMART_SEC_SIZE);
if (ioctl ( device , HDIO_DRIVE_CMD, (unsigned char *) &buf ) != 0)
{
perror ("Smart Thresholds Read failed");
return -1;
}
return 0;
}
int ataEnableSmart (int device )
{
unsigned char parms[4] = { WIN_SMART, 1, SMART_ENABLE, 0};
if (ioctl ( device , HDIO_DRIVE_CMD, &parms ) != 0)
{
perror ("Smart Enable failed");
return -1;
}
return 0;
}
int ataDisableSmart (int device )
{
unsigned char parms[4] = { WIN_SMART, 1, SMART_DISABLE, 0};
if (ioctl ( device , HDIO_DRIVE_CMD, &parms ) != 0)
{
perror ("Smart Disable failed");
return -1;
}
return 0;
}
int ataEnableAutoSave(int device){
unsigned char parms[4] = { WIN_SMART, 241, SMART_AUTOSAVE, 0};
if (ioctl ( device , HDIO_DRIVE_CMD, &parms ) != 0)
{
perror ("Smart Enable Auto-save failed");
return -1;
}
return 0;
};
int ataDisableAutoSave(int device){
unsigned char parms[4] = { WIN_SMART, 0, SMART_AUTOSAVE, 0};
if (ioctl ( device , HDIO_DRIVE_CMD, &parms ) != 0)
{
perror ("Smart Disable Auto-save failed");
return -1;
}
return 0;
};
int ataEnableAutoOffline (int device )
{
/* timer hard coded to 4 hours */
unsigned char parms[4] = { WIN_SMART, 248, SMART_AUTO_OFFLINE, 0};
if (ioctl ( device , HDIO_DRIVE_CMD, &parms ) != 0)
{
perror ("Smart Enable Automatic Offline failed");
return -1;
}
return 0;
}
int ataDisableAutoOffline (int device )
{
unsigned char parms[4] = { WIN_SMART, 0, SMART_AUTO_OFFLINE, 0};
if (ioctl ( device , HDIO_DRIVE_CMD, &parms ) != 0)
{
perror ("Smart Disable Automatic Offline failed");
return -1;
}
return 0;
}
// Not being used correctly. Must examine the CL and CH registers to
// see what the smart status was. How to fix this? I don't know...
int ataSmartStatus (int device ){
unsigned char parms[4] = { WIN_SMART, 0, SMART_STATUS, 0};
if (ioctl ( device , HDIO_DRIVE_CMD, &parms))
return -1;
return 0;
}
int ataSmartTest (int device, int testtype)
{
unsigned char parms[4] = { WIN_SMART, testtype,
SMART_IMMEDIATE_OFFLINE, 0};
if (ioctl ( device , HDIO_DRIVE_CMD, &parms) != 0)
{
perror ("Smart Offline failed");
return -1;
}
printf("Completed Off-line command\n");
return 0;
}
int ataSmartOfflineTest (int device)
{
return ataSmartTest( device, OFFLINE_FULL_SCAN );
}
int ataSmartShortSelfTest (int device)
{
return ataSmartTest( device, SHORT_SELF_TEST );
}
int ataSmartExtendSelfTest (int device)
{
return ataSmartTest( device, EXTEND_SELF_TEST );
}
int ataSmartShortCapSelfTest (int device)
{
return ataSmartTest( device, SHORT_CAPTIVE_SELF_TEST );
}
int ataSmartExtendCapSelfTest (int device)
{
return ataSmartTest( device, EXTEND_CAPTIVE_SELF_TEST );
}
int ataSmartSelfTestAbort (int device)
{
return ataSmartTest( device, 127 );
}
/* Test Time Functions */
int isOfflineTestTime ( struct ata_smart_values data)
{
return (int) data.total_time_to_complete_off_line;
}
int isShortSelfTestTime ( struct ata_smart_values data)
{
return (int) data.short_test_completion_time;
}
int isExtendedSelfTestTime ( struct ata_smart_values data)
{
return (int) data.extend_test_completion_time;
}
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 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;
}
// Loop over all valid attributes. If they are prefailure attributes
// and are below the threshold value, then return the index of the
// lowest failing attribute. Return 0 if all prefailure attributes
// are in bounds.
int ataCheckSmart (struct ata_smart_values data, struct ata_smart_thresholds thresholds){
int i;
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))
return i;
}
return 0;
}
This diff is collapsed.
This diff is collapsed.
// $Id: scsiprint.cpp,v 1.6 2002/10/15 14:24:27 ballen4705 Exp $
/*
* scsiprint.c
*
* Home page of code is: http://smartmontools.sourceforge.net
*
* Copyright (C) 2002 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 <string.h>
#include <fcntl.h>
#include <errno.h>
#include "smartctl.h"
#include "extern.h"
#include "scsicmds.h"
#include "scsiprint.h"
#define GBUF_SIZE 65535
UINT8 gBuf[GBUF_SIZE];
UINT8 gSmartPage = 0;
UINT8 gTempPage = 0;
UINT8 gSelfTestPage = 0;
UINT8 gStartStopPage = 0;
UINT8 gTapeAlertsPage = 0;
void scsiGetSupportPages ( int device)
{
int i;
if (logsense ( device , SUPPORT_LOG_PAGES, (UINT8 *) &gBuf) != 0)
{
perror ( "Log Sense failed");
exit (1);
}
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 SMART_PAGE:
gSmartPage = 1;
break;
case TAPE_ALERTS_PAGE:
gTapeAlertsPage = 1;
break;
default:
break;
}
}
}
void scsiGetSmartData (int device)
{
UINT8 returnvalue;
UINT8 currenttemp;
UINT8 triptemp;
if ( scsiCheckSmart(device, gSmartPage,
&returnvalue, &currenttemp, &triptemp ) != 0)
{
perror ( "scsiGetSmartData Failed");
exit (1);
}
if ( returnvalue )
printf("S.M.A.R.T. Sense: (%02x) %s\n", (UINT8) returnvalue,
scsiSmartGetSenseCode(returnvalue));
else
printf("S.M.A.R.T. Sense: Ok!\n");
if ( (currenttemp || triptemp) && !gTempPage)
{
printf("Current Drive Temperature: %d C\n", currenttemp);
printf("Drive Trip Temperature: %d C\n", triptemp);
}
}
void scsiGetTapeAlertsData (int device)
{
unsigned short pagelength;
unsigned short parametercode;
int i;
int failure = 0;
if ( logsense( device, TAPE_ALERTS_PAGE, (UINT8 *) &gBuf) != 0)
{
perror ( "scsiGetSmartData Failed");
exit (1);
}
if ( gBuf[0] != 0x2e )
{
printf("TapeAlerts Log Sense Failed\n");
exit(-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])
{
printf("Tape Alerts Error!!!\n%s\n",
scsiTapeAlertsTapeDevice(parametercode));
failure = 1;
}
}
if(!failure)
printf("No Tape Alerts Failure\n");
}
void scsiGetStartStopData ( int device)
{
UINT32 currentStartStop;
UINT32 recommendedStartStop;
if ( logsense( device, STARTSTOP_CYCLE_COUNTER_PAGE, (UINT8 *) &gBuf) != 0)
{
perror ( "scsiGetStartStopData Failed");
exit (1);
}
if ( gBuf[0] != STARTSTOP_CYCLE_COUNTER_PAGE )
{
printf("StartStop Log Sense Failed\n");
exit(-1);
}
recommendedStartStop= (UINT32) gBuf[28]<< 24 | gBuf[29] << 8 |
gBuf[30] << 16 | gBuf[31];
currentStartStop= (UINT32) gBuf[36]<< 24 | gBuf[37] << 8 |
gBuf[38] << 16 | gBuf[39];
printf("Current start stop count: %u times\n", currentStartStop);
printf("Recommended start stop count: %u times\n", recommendedStartStop);
}
void scsiGetDriveInfo ( int device)
{
char manufacturer[9];
char product[17];
char revision[5];
UINT8 smartsupport;
if (stdinquiry ( device, (UINT8 *) &gBuf) != 0)
{
perror ( "Standard Inquiry failed");
}
memset ( &manufacturer, 0, 8);
manufacturer[8] = '\0';
strncpy ((char *) &manufacturer, (char *) &gBuf[8], 8);
memset ( &product, 0, 16);
strncpy ((char *) &product, (char *) &gBuf[16], 16);
product[16] = '\0';
memset ( &revision, 0, 4);
strncpy ((char *) &revision, (char *) &gBuf[32], 4);
revision[4] = '\0';
printf("Device: %s %s Version: %s\n", manufacturer, product, revision);
if ( scsiSmartSupport( device, (UINT8 *) &smartsupport) != 0)
{
printf("Device does not support %s\n",(gBuf[0] & 0x1f)?
"TapeAlerts": "S.M.A.R.T.");
exit (1);
}
printf("Device supports %s and is %s\n%s\n",
(gBuf[0] & 0x1f)? "TapeAlerts" : "S.M.A.R.T.",
(smartsupport & DEXCPT_ENABLE)? "Disable" : "Enabled",
(smartsupport & EWASC_ENABLE)? "Temperature Warning Enabled":
"Temperature Warning Disabled or Not Supported");
}
void scsiSmartEnable( int device)
{
/* Enable Exception Control */
if ( scsiSmartDEXCPTDisable(device) != 0)
{
exit (1);
}
printf("S.M.A.R.T. enabled\n");
if (scsiSmartEWASCEnable(device) != 0)
{
printf("Temperature Warning not Supported\n");
}
else
{
printf("Temperature Warning Enabled\n");
}
return;
}
void scsiSmartDisable (int device)
{
if ( scsiSmartDEXCPTEnable(device) != 0)
{
exit (1);
}
printf("S.M.A.R.T. Disabled\n");
}
void scsiPrintTemp (int device)
{
UINT8 temp;
UINT8 trip;
if ( scsiGetTemp(device, &temp, &trip) != 0)
{
exit (1);
}
printf("Current Drive Temperature: %d C\n", temp);
printf("Drive Trip Temperature: %d C\n", trip);
}
void scsiPrintStopStart ( int device )
{
/**
unsigned int css;
if ( scsiGetStartStop(device, unsigned int *css) != 0)
{
exit (1);
}
printf ("Start Stop Count: %d\n", css);
**/
}
void scsiPrintMain (int fd)
{
if (driveinfo)
scsiGetDriveInfo(fd);
if (smartenable)
scsiSmartEnable(fd);
if (smartdisable)
scsiSmartDisable(fd);
if (checksmart)
{
scsiGetSupportPages (fd);
if(gTapeAlertsPage)
scsiGetTapeAlertsData (fd);
else
{
scsiGetSmartData(fd);
if(gTempPage)
scsiPrintTemp(fd);
if(gStartStopPage)
scsiGetStartStopData (fd);
}
}
if ( smartexeoffimmediate )
{
if ( scsiSmartOfflineTest (fd) != 0)
{
printf( "Smartctl: Smart Offline Failed\n");
exit(-1);
}
printf ("Drive Command Successful offline test has begun\n");
printf ("Use smartctl -%c to abort test\n", SMARTSELFTESTABORT);
}
if ( smartshortcapselftest )
{
if ( scsiSmartShortCapSelfTest (fd) != 0)
{
printf( "Smartctl: Smart Short Self Test Failed\n");
exit(-1);
}
printf ("Drive Command Successful Short Self test has begun\n");
printf ("Use smartctl -%c to abort test\n", SMARTSELFTESTABORT);
}
if ( smartshortselftest )
{
if ( scsiSmartShortSelfTest (fd) != 0)
{
printf( "Smartctl: Smart Short Self Test Failed\n");
exit(-1);
}
printf ("Drive Command Successful Short Self test has begun\n");
printf ("Use smartctl -%c to abort test\n", SMARTSELFTESTABORT);
}
if ( smartextendselftest )
{
if ( scsiSmartExtendSelfTest (fd) != 0)
{
printf( "S.M.A.R.T. Extended Self Test Failed\n");
exit(-1);
}
printf ("Drive Command Successful Extended Self test has begun\n");
printf ("Use smartctl -%c to abort test\n", SMARTSELFTESTABORT);
}
if ( smartextendcapselftest )
{
if ( scsiSmartExtendCapSelfTest (fd) != 0)
{
printf( "S.M.A.R.T. Extended Self Test Failed\n");
exit(-1);
}
printf ("Drive Command Successful Extended Self test has begun\n");
printf ("Use smartctl -%c to abort test\n", SMARTSELFTESTABORT);
}
if ( smartselftestabort )
{
if ( scsiSmartSelfTestAbort (fd) != 0)
{
printf( "S.M.A.R.T. Self Test Abort Failed\n");
exit(-1);
}
printf ("Drive Command Successful self test aborted\n");
}
}
// $Id: smartctl.cpp,v 1.9 2002/10/15 14:24:27 ballen4705 Exp $
/*
* smartctl.c
*
* Home page of code is: http://smartmontools.sourceforge.net
*
* Copyright (C) 2002 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 "smartctl.h"
#include "atacmds.h"
#include "ataprint.h"
#include "scsicmds.h"
#include "scsiprint.h"
unsigned char driveinfo = FALSE;
unsigned char checksmart = FALSE;
unsigned char smartvendorattrib = FALSE;
unsigned char generalsmartvalues = FALSE;
unsigned char smartselftestlog = FALSE;
unsigned char smarterrorlog = FALSE;
unsigned char smartdisable = FALSE;
unsigned char smartenable = FALSE;
unsigned char smartstatus = FALSE;
unsigned char smartexeoffimmediate = FALSE;
unsigned char smartshortselftest = FALSE;
unsigned char smartextendselftest = FALSE;
unsigned char smartshortcapselftest = FALSE;
unsigned char smartextendcapselftest = FALSE;
unsigned char smartselftestabort = FALSE;
unsigned char smartautoofflineenable = FALSE;
unsigned char smartautoofflinedisable = FALSE;
unsigned char smartautosaveenable = FALSE;
unsigned char smartautosavedisable = FALSE;
unsigned char printcopyleft = FALSE;
unsigned char smart009minutes = FALSE;
/* void Usage (void)
prints help information for command syntax */
void Usage ( void){
printf( "usage: smartctl -[options] [device]\n");
printf( "Read Only Options:\n");
printf( "\t\t%c\t\tShow version, copyright and license information\n", PRINTCOPYLEFT);
printf( "\t\t%c\t\tShow all S.M.A.R.T. Information (ATA and SCSI)\n", SMARTVERBOSEALL);
printf( "\t\t%c\t\tShow S.M.A.R.T. Drive Info (ATA and SCSI)\n", DRIVEINFO);
printf( "\t\t%c\t\tShow S.M.A.R.T. Status (ATA and SCSI)\n", CHECKSMART);
printf( "\t\t%c\t\tShow S.M.A.R.T. General Attributes (ATA Only)\n", GENERALSMARTVALUES);
printf( "\t\t%c\t\tShow S.M.A.R.T. Vendor Attributes (ATA Only)\n", SMARTVENDORATTRIB);
printf( "\t\t%c\t\tShow S.M.A.R.T. Drive Error Log (ATA Only\n", SMARTERRORLOG);
printf( "\t\t%c\t\tShow S.M.A.R.T. Drive Self Test Log (ATA Only)\n", SMARTSELFTESTLOG);
printf( "\n");
printf( "Vendor-specific Display Options:\n");
printf( "\t\t%c\t\tRaw Attribute 009 is minutes (ATA Only)\n", SMART009MINUTES);
printf( "\n");
printf( "Enable/Disable Options:\n");
printf( "\t\t%c\t\tEnable S.M.A.R.T. data collection (ATA and SCSI)\n",SMARTENABLE);
printf( "\t\t%c\t\tDisable S.M.A.R.T. data collection (ATA and SCSI)\n",SMARTDISABLE);
printf( "\t\t%c\t\tEnable S.M.A.R.T. Automatic Offline Test (ATA Only)\n",SMARTAUTOOFFLINEENABLE);
printf( "\t\t%c\t\tDisable S.M.A.R.T. Automatic Offline Test (ATA Only)\n",SMARTAUTOOFFLINEDISABLE);
printf( "\t\t%c\t\tEnable S.M.A.R.T. Attribute Autosave (ATA Only)\n",SMARTAUTOSAVEENABLE);
printf( "\t\t%c\t\tDisable S.M.A.R.T. Attribute Autosave (ATA Only)\n",SMARTAUTOSAVEDISABLE);
printf( "\n");
printf( "Test Options:\n");
printf( "\t\t%c\t\tExecute Off-line data collection (ATA Only)\n", SMARTEXEOFFIMMEDIATE);
printf( "\t\t%c\t\tExecute Short Self Test (ATA Only)\n", SMARTSHORTSELFTEST );
printf( "\t\t%c\t\tExecute Short Self Test (Captive Mode) (ATA Only)\n", SMARTSHORTCAPSELFTEST );
printf( "\t\t%c\t\tExecute Extended Self Test (ATA Only)\n", SMARTEXTENDSELFTEST );
printf( "\t\t%c\t\tExecute Extended Self Test (Captive Mode) (ATA Only)\n", SMARTEXTENDCAPSELFTEST );
printf( "\t\t%c\t\tExecute Self Test Abort (ATA Only)\n\n", SMARTSELFTESTABORT );
printf( "Examples:\n");
printf("\tsmartctl -etf /dev/hda (Enables S.M.A.R.T. on first disk)\n");
printf("\tsmartctl -a /dev/hda (Prints all S.M.A.R.T. information)\n");
printf("\tsmartctl -X /dev/hda (Executes extended disk self-test)\n");
printf("Please see the man pages or the web site for further information.\n");
}
const char opts[] = {
DRIVEINFO, CHECKSMART, SMARTVERBOSEALL, SMARTVENDORATTRIB,
GENERALSMARTVALUES, SMARTERRORLOG, SMARTSELFTESTLOG, SMARTDISABLE,
SMARTENABLE, SMARTAUTOOFFLINEENABLE, SMARTAUTOOFFLINEDISABLE,
SMARTEXEOFFIMMEDIATE, SMARTSHORTSELFTEST, SMARTEXTENDSELFTEST,
SMARTSHORTCAPSELFTEST, SMARTEXTENDCAPSELFTEST, SMARTSELFTESTABORT,
SMARTAUTOSAVEENABLE,SMARTAUTOSAVEDISABLE,PRINTCOPYLEFT,SMART009MINUTES,'\0'
};
/* Takes command options and sets features to be run */
void ParseOpts (int argc, char** argv){
int optchar;
extern char *optarg;
extern int optopt, optind, opterr;
opterr=1;
while (-1 != (optchar = getopt(argc, argv, opts))) {
switch (optchar){
case SMART009MINUTES:
smart009minutes=TRUE;
break;
case PRINTCOPYLEFT :
printcopyleft=TRUE;
break;
case DRIVEINFO :
driveinfo = TRUE;
break;
case CHECKSMART :
driveinfo = TRUE;
checksmart = TRUE;
break;
case SMARTVERBOSEALL :
driveinfo = TRUE;
checksmart = TRUE;
generalsmartvalues = TRUE;
smartvendorattrib = TRUE;
smarterrorlog = TRUE;
smartselftestlog = TRUE;
break;
case SMARTVENDORATTRIB :
smartvendorattrib = TRUE;
break;
case GENERALSMARTVALUES :
generalsmartvalues = TRUE;
break;
case SMARTERRORLOG :
smarterrorlog = TRUE;
break;
case SMARTSELFTESTLOG :
smartselftestlog = TRUE;
break;
case SMARTDISABLE :
smartdisable = TRUE;
break;
case SMARTENABLE :
smartenable = TRUE;
break;
case SMARTAUTOSAVEENABLE:
smartautosaveenable = TRUE;
break;
case SMARTAUTOSAVEDISABLE:
smartautosavedisable = TRUE;
break;
case SMARTAUTOOFFLINEENABLE:
smartautoofflineenable = TRUE;
break;
case SMARTAUTOOFFLINEDISABLE:
smartautoofflinedisable = TRUE;
break;
case SMARTEXEOFFIMMEDIATE:
smartexeoffimmediate = TRUE;
break;
case SMARTSHORTSELFTEST :
smartshortselftest = TRUE;
break;
case SMARTEXTENDSELFTEST :
smartextendselftest = TRUE;
break;
case SMARTSHORTCAPSELFTEST:
smartshortcapselftest = TRUE;
break;
case SMARTEXTENDCAPSELFTEST:
smartextendcapselftest = TRUE;
break;
case SMARTSELFTESTABORT:
smartselftestabort = TRUE;
break;
default:
Usage();
exit (-1);
}
if ( (smartexeoffimmediate + smartshortselftest +
smartextendselftest + smartshortcapselftest +
smartextendcapselftest ) > 1){
Usage();
printf ("\n ERROR: smartctl can only run a single test at a time \n");
exit(-1);
}
}
}
/* Main Program */
int main (int argc, char **argv){
int fd;
char *device;
printf("smartctl version %d.%d-%d Copyright (C) 2002 Bruce Allen\n",RELEASE_MAJOR,RELEASE_MINOR,SMARTMONTOOLS_VERSION);
printf("Home page of smartctl is %s\n\n",PROJECTHOME);
// Part input arguments
ParseOpts (argc,argv);
// Print Copyright/License info if needed
if (printcopyleft){
printf("smartctl comes with ABSOLUTELY NO WARRANTY. This\n");
printf("is free software, and you are welcome to redistribute it\n");
printf("under the terms of the GNU General Public License Version 2.\n");
printf("See http://www.gnu.org for further details.\n\n");
printf("CVS version ID %s\n","$Id: smartctl.cpp,v 1.9 2002/10/15 14:24:27 ballen4705 Exp $");
exit(0);
}
// Further argument checking
if ( argc != 3 ){
Usage();
exit (-1);
}
/* open device */
fd = open ( device=argv[2], O_RDWR );
if ( fd < 0) {
perror ( "Device open failed");
exit(-1);
}
if ( device[5] == 'h')
ataPrintMain (fd );
else if (device[5] == 's')
scsiPrintMain (fd);
else
Usage();
return 0;
}
// $Id: smartd.cpp,v 1.9 2002/10/15 14:24:27 ballen4705 Exp $
/*
* smartd.c
*
* Home page of code is: http://smartmontools.sourceforge.net
*
* Copyright (C) 2002 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 <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <linux/hdreg.h>
#include <syslog.h>
#include <stdarg.h>
#include "atacmds.h"
#include "scsicmds.h"
#include "smartd.h"
int daemon_init(void){
pid_t pid;
if ( (pid = fork()) < 0)
// unable to fork!
return -1;
else if (pid != 0)
// we are the parent process -- exit
exit (0);
// from here on, we are the child process
setsid ();
chdir("/");
umask(0);
return(0);
}
// This function prints either to stdout or to the syslog as needed
void printout(int priority,char *fmt, ...){
va_list ap;
// initialize variable argument list
va_start(ap,fmt);
if (debugmode)
vprintf(fmt,ap);
else
vsyslog(priority,fmt,ap);
va_end(ap);
return;
}
/* prints help information for command syntax */
void Usage ( void){
printout(LOG_INFO,"smartd version %d.%d-%d - S.M.A.R.T. Daemon\n",
RELEASE_MAJOR, RELEASE_MINOR,SMARTMONTOOLS_VERSION);
printout(LOG_INFO,"usage: smartd -[opts] \n");
printout(LOG_INFO,"Read Only Commands:\n");
printout(LOG_INFO,"\t\t%c\t\tStart smartd in debug Mode\n",DEBUGMODE);
printout(LOG_INFO,"\t\t%c\t\tPrint License and Copyright information\n",PRINTCOPYLEFT);
}
// scan to see what ata devices there are, and if they support SMART
void atadevicescan ( atadevices_t *devices){
int i;
int fd;
struct hd_driveid drive;
char device[] = "/dev/hda";
for(i=0;i<MAXATADEVICES;i++,device[7]++ ){
printout(LOG_INFO,"Reading Device %s\n", device);
fd = open ( device , O_RDWR );
if ( fd < 0)
// no such device
continue;
if (ataReadHDIdentity (fd,&drive) || !ataSmartSupport(drive) || ataEnableSmart(fd)){
// device exists, but not able to do SMART
close(fd);
printout(LOG_INFO,"Device: %s, Found but not SMART capable, or couldn't enable SMART\n",device);
continue;
}
// device exists, and does SMART. Add to list
devices[numatadevices].fd = fd;
strcpy(devices[numatadevices].devicename, device);
devices[numatadevices].drive = drive;
if (ataReadSmartValues (fd,&devices[numatadevices].smartval)){
printout(LOG_INFO,"Device: %s, Read Smart Values Failed\n",device);
}
if (ataReadSmartThresholds (fd,&devices[numatadevices].smartthres)){
printout(LOG_INFO,"Device: %s, Read Smart Thresholds Failed\n",device);
}
printout(LOG_INFO,"%s Found and is SMART capable\n",device);
devices[numatadevices].selftest =
isSupportSelfTest(devices[numatadevices].smartval);
numatadevices++;
}
}
// This function is hard to read and ought to be rewritten
// A couple of obvious questions -- why isn't fd always closed if not used?
// Why in the world is the four-byte integer cast to a pointer to an eight-byte object??
void scsidevicescan ( scsidevices_t *devices){
int i, fd, smartsupport;
unsigned char tBuf[4096];
char device[] = "/dev/sda";
for(i = 0; i < MAXSCSIDEVICES ; i++,device[7]++ ){
printout(LOG_INFO,"Reading Device %s\n", device);
fd = open ( device , O_RDWR );
if ( fd >= 0 && !testunitready (fd)) {
if (modesense ( fd, 0x1c, (UINT8 *) &tBuf) != 0){
printout(LOG_INFO,"Device: %s, Failed read of ModePage 1C \n", device);
close(fd);
}
else
if ( scsiSmartSupport( fd, (UINT8 *) &smartsupport) == 0){
if (!(smartsupport & DEXCPT_ENABLE)){
devices[numscsidevices].fd = fd;
strcpy(devices[numscsidevices].devicename,device);
printout(LOG_INFO, "Device: %s, Found and is SMART capable\n",device);
if (logsense ( fd , SUPPORT_LOG_PAGES, (UINT8 *) &tBuf) == 0){
for ( i = 4; i < tBuf[3] + LOGPAGEHDRSIZE ; i++){
switch ( tBuf[i]){
case TEMPERATURE_PAGE:
devices[numscsidevices].TempPageSupported = 1;
break;
case SMART_PAGE:
devices[numscsidevices].SmartPageSupported = 1;
break;
default:
break;
}
}
}
numscsidevices++;
}
}
}
}
}
void ataCompareSmartValues (atadevices_t *device, struct ata_smart_values new ){
int i;
int oldval,newval,idold,idnew;
for ( i =0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++){
// which device is it?
idnew=new.vendor_attributes[i].id;
idold=device->smartval.vendor_attributes[i].id;
if (idold && idnew){
// if it's a valid attribute, compare values
newval=new.vendor_attributes[i].current;
oldval=device->smartval.vendor_attributes[i].current;
if (oldval!=newval)
// values have changed; print them
printout(LOG_INFO, "Device: %s, S.M.A.R.T. Attribute: %i Changed from %i to %i\n",
device->devicename,idnew,oldval,newval);
}
}
}
int ataCheckDevice( atadevices_t *drive){
struct ata_smart_values tempsmartval;
struct ata_smart_thresholds tempsmartthres;
int failed;
// Coming into this function, *drive contains the last values measured,
// and we read the NEW values into tempsmartval
if (ataReadSmartValues(drive->fd,&tempsmartval))
printout(LOG_INFO, "%s:Failed to read smart values\n", drive->devicename);
// and we read the new thresholds into tempsmartthres
if (ataReadSmartThresholds (drive->fd, &tempsmartthres))
printout(LOG_INFO, "%s:Failed to read smart thresholds\n",drive->devicename);
// See if any vendor attributes are below minimum, and print them out
if ((failed=ataCheckSmart(tempsmartval,tempsmartthres)))
printout(LOG_CRIT,"Device: %s, Failed attribute: %i\n",drive->devicename,failed);
// see if any values have changed. Second argument is new values
ataCompareSmartValues (drive , tempsmartval);
// Save the new values into *drive for the next time around
drive->smartval = tempsmartval;
drive->smartthres = tempsmartthres;
return 0;
}
int scsiCheckDevice( scsidevices_t *drive)
{
UINT8 returnvalue;
UINT8 currenttemp;
UINT8 triptemp;
currenttemp = triptemp = 0;
if (scsiCheckSmart( drive->fd, drive->SmartPageSupported, &returnvalue, &currenttemp, &triptemp ) != 0)
printout(LOG_INFO, "%s:Failed to read smart values\n", drive->devicename);
if (returnvalue)
printout(LOG_CRIT, "Device: %s, S.M.A.R.T. Failure: (%02x) %s\n", drive->devicename,
returnvalue, scsiSmartGetSenseCode( returnvalue) );
else
printout(LOG_INFO,"Device: %s, Acceptable attribute: %d\n", drive->devicename, returnvalue);
if (currenttemp){
if ( (currenttemp != drive->Temperature) && ( drive->Temperature) )
printout(LOG_INFO, "Device: %s, Temperature changed %d degrees to %d degrees since last reading\n",
drive->devicename, (int) (currenttemp - drive->Temperature), (unsigned int) currenttemp );
drive->Temperature = currenttemp;
}
return 0;
}
void CheckDevices ( atadevices_t *atadevices, scsidevices_t *scsidevices)
{
int i;
while (1){
for (i = 0; i < numatadevices;i++)
ataCheckDevice ( &atadevices[i]);
for (i = 0; i < numscsidevices;i++)
scsiCheckDevice ( &scsidevices[i]);
sleep ( checktime );
}
}
char copyleftstring[]=
"Home page of smartd is " PROJECTHOME "\n\n"
"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"
"CVS Version ID $Id: smartd.cpp,v 1.9 2002/10/15 14:24:27 ballen4705 Exp $\n";
const char opts[] = { DEBUGMODE, EMAILNOTIFICATION, PRINTCOPYLEFT,'\0' };
/* Main Program */
int main (int argc, char **argv){
atadevices_t atadevices[MAXATADEVICES], *atadevicesptr;
scsidevices_t scsidevices[MAXSCSIDEVICES], *scsidevicesptr;
int optchar;
extern char *optarg;
extern int optopt, optind, opterr;
numatadevices=0;
numscsidevices=0;
scsidevicesptr = scsidevices;
atadevicesptr = atadevices;
opterr=1;
while (-1 != (optchar = getopt(argc, argv, opts))){
switch(optchar) {
case PRINTCOPYLEFT:
printcopyleft=TRUE;
break;
case DEBUGMODE :
debugmode = TRUE;
break;
case EMAILNOTIFICATION:
emailnotification = TRUE;
break;
case '?':
default:
debugmode=1;
Usage();
exit(-1);
}
}
if (printcopyleft){
debugmode=1;
printout(LOG_INFO,"smartd version %d.%d-%d Copyright (C) Bruce Allen 2002\n",
RELEASE_MAJOR,RELEASE_MINOR,SMARTMONTOOLS_VERSION);
printout(LOG_INFO,copyleftstring);
exit(0);
}
printout(LOG_INFO,"smartd version %d.%d-%d Copyright (C) Bruce Allen 2002\n",
RELEASE_MAJOR,RELEASE_MINOR,SMARTMONTOOLS_VERSION);
if (!debugmode){
daemon_init();
}
/* fork into independent process */
atadevicescan (atadevicesptr);
scsidevicescan (scsidevicesptr);
CheckDevices ( atadevicesptr, scsidevicesptr);
return 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
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment