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

This commit was manufactured by cvs2svn to create tag

'RELEASE_5_0_40'.

git-svn-id: https://smartmontools.svn.sourceforge.net/svnroot/smartmontools/tags/RELEASE_5_0_40@255 4ea69e1a-61f1-4043-bf83-b5c94c648137
parent 028defad
No related branches found
No related tags found
No related merge requests found
Showing with 0 additions and 5290 deletions
# 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.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* 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 "scsicmds.h"
#include "scsiprint.h"
#include "extern.h"
#define GBUF_SIZE 65535
const char* CVSid4="$Id: scsiprint.cpp,v 1.10 2002/10/28 23:46:59 ballen4705 Exp $"
CVSID3 CVSID4 CVSID5 CVSID6;
// control block which points to external global control variables
extern atamainctrl *con;
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 (con->driveinfo)
scsiGetDriveInfo(fd);
if (con->smartenable)
scsiSmartEnable(fd);
if (con->smartdisable)
scsiSmartDisable(fd);
if (con->checksmart)
{
scsiGetSupportPages (fd);
if(gTapeAlertsPage)
scsiGetTapeAlertsData (fd);
else
{
scsiGetSmartData(fd);
if(gTempPage)
scsiPrintTemp(fd);
if(gStartStopPage)
scsiGetStartStopData (fd);
}
}
if ( con->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 ( con->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 ( con->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 ( con->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 ( con->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 ( con->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");
}
}
/*
* 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 <stdarg.h>
#include "smartctl.h"
#include "atacmds.h"
#include "ataprint.h"
#include "scsicmds.h"
#include "scsiprint.h"
#include "extern.h"
extern const char *CVSid1, *CVSid2, *CVSid3, *CVSid4;
const char* CVSid5="$Id: smartctl.cpp,v 1.27 2002/11/07 19:07:20 ballen4705 Exp $"
CVSID1 CVSID2 CVSID3 CVSID4 CVSID5 CVSID6;
// This is a block containing all the "control variables". We declare
// this globally in this file, and externally in other files.
atamainctrl *con=NULL;
void printslogan(){
pout("smartctl version %d.%d-%d Copyright (C) 2002 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,CVSid1);
pout("%s",out);
printone(out,CVSid2);
pout("%s",out);
printone(out,CVSid3);
pout("%s",out);
printone(out,CVSid4);
pout("%s",out);
printone(out,CVSid5);
pout("%s",out);
return;
}
/* void prints help information for command syntax */
void Usage ( void){
printf("Usage: smartctl -[options] [device]\n");
printf("\nShow Information Options:\n");
printf(" %c Show Version, Copyright and License info\n", PRINTCOPYLEFT);
printf(" %c Show SMART Drive Info (ATA/SCSI)\n",DRIVEINFO);
printf(" %c Show all SMART Information (ATA/SCSI)\n",SMARTVERBOSEALL);
printf("\nRun-time Behavior Options:\n");
printf(" %c Quiet: only show SMART Drive Errors (ATA Only)\n", QUIETMODE);
printf(" %c Very Quiet: no display, use Exit Status (ATA Only)\n", VERYQUIETMODE);
printf(" %c Device is an ATA Device (ATA Only)\n", NOTSCSIDEVICE);
printf(" %c Device is a SCSI Device (SCSI Only)\n", NOTATADEVICE);
printf(" %c Permissive: continue on Mandatory fails (ATA Only)\n", PERMISSIVE);
printf(" %c Conservative: exit if Optional Cmd fail (ATA Only)\n", ULTRACONSERVATIVE);
printf(" %c Warning: exit if Struct Checksum bad (ATA Only)\n", EXITCHECKSUMERROR);
printf("\nSMART Feature Enable/Disable Commands:\n");
printf(" %c Enable SMART data collection (ATA/SCSI)\n", SMARTENABLE);
printf(" %c Disable SMART data collection (ATA/SCSI)\n", SMARTDISABLE);
printf(" %c Enable SMART Automatic Offline Test (ATA Only)\n", SMARTAUTOOFFLINEENABLE);
printf(" %c Disable SMART Automatic Offline Test (ATA Only)\n", SMARTAUTOOFFLINEDISABLE);
printf(" %c Enable SMART Attribute Autosave (ATA Only)\n", SMARTAUTOSAVEENABLE);
printf(" %c Disable SMART Attribute Autosave (ATA Only)\n", SMARTAUTOSAVEDISABLE);
printf("\nRead and Display Data Options:\n");
printf(" %c Show SMART Status (ATA/SCSI)\n", CHECKSMART);
printf(" %c Show SMART General Attributes (ATA Only)\n", GENERALSMARTVALUES);
printf(" %c Show SMART Vendor Attributes (ATA Only)\n", SMARTVENDORATTRIB);
printf(" %c Show SMART Drive Error Log (ATA Only\n", SMARTERRORLOG);
printf(" %c Show SMART Drive Self Test Log (ATA Only)\n", SMARTSELFTESTLOG);
printf("\nVendor-specific Attribute Display Options:\n");
printf(" %c Raw Attribute id=009 stored in minutes (ATA Only)\n", SMART009MINUTES);
printf("\nSelf-Test Options (no more than one):\n");
printf(" %c Execute Off-line data collection (ATA/SCSI)\n", SMARTEXEOFFIMMEDIATE);
printf(" %c Execute Short Self Test (ATA/SCSI)\n", SMARTSHORTSELFTEST );
printf(" %c Execute Short Self Test (Captive Mode) (ATA/SCSI)\n", SMARTSHORTCAPSELFTEST );
printf(" %c Execute Extended Self Test (ATA/SCSI)\n", SMARTEXTENDSELFTEST );
printf(" %c Execute Extended Self Test (Captive) (ATA/SCSI)\n", SMARTEXTENDCAPSELFTEST );
printf(" %c Execute Self Test Abort (ATA/SCSI)\n", SMARTSELFTESTABORT );
printf("\nExamples:\n");
printf(" smartctl -etf /dev/hda (Enables SMART on first disk)\n");
printf(" smartctl -a /dev/hda (Prints all SMART information)\n");
printf(" smartctl -X /dev/hda (Executes extended disk self-test)\n");
printf(" smartctl -qvL /dev/hda (Prints Self-Test & Attribute errors.)\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,
QUIETMODE,VERYQUIETMODE,NOTSCSIDEVICE,NOTATADEVICE,
EXITCHECKSUMERROR,ULTRACONSERVATIVE,PERMISSIVE,
'h','?','\0'
};
unsigned char printcopyleft=0,tryata=0,tryscsi=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;
memset(con,0,sizeof(*con));
con->testcase=-1;
opterr=optopt=0;
while (-1 != (optchar = getopt(argc, argv, opts))) {
switch (optchar){
case EXITCHECKSUMERROR:
con->checksumfail=1;
break;
case PERMISSIVE:
con->permissive=1;
break;
case ULTRACONSERVATIVE:
con->conservative=1;
break;
case NOTATADEVICE:
tryata=0;
tryscsi=1;
break;
case NOTSCSIDEVICE:
tryata=1;
tryscsi=0;
break;
case QUIETMODE:
con->quietmode=TRUE;
break;
case VERYQUIETMODE:
con->veryquietmode=TRUE;
break;
case SMART009MINUTES:
con->smart009minutes=TRUE;
break;
case PRINTCOPYLEFT :
printcopyleft=TRUE;
break;
case DRIVEINFO :
con->driveinfo = TRUE;
break;
case CHECKSMART :
con->checksmart = TRUE;
break;
case SMARTVERBOSEALL :
con->driveinfo = TRUE;
con->checksmart = TRUE;
con->generalsmartvalues = TRUE;
con->smartvendorattrib = TRUE;
con->smarterrorlog = TRUE;
con->smartselftestlog = TRUE;
break;
case SMARTVENDORATTRIB :
con->smartvendorattrib = TRUE;
break;
case GENERALSMARTVALUES :
con->generalsmartvalues = TRUE;
break;
case SMARTERRORLOG :
con->smarterrorlog = TRUE;
break;
case SMARTSELFTESTLOG :
con->smartselftestlog = TRUE;
break;
case SMARTDISABLE :
con->smartdisable = TRUE;
break;
case SMARTENABLE :
con->smartenable = TRUE;
break;
case SMARTAUTOSAVEENABLE:
con->smartautosaveenable = TRUE;
break;
case SMARTAUTOSAVEDISABLE:
con->smartautosavedisable = TRUE;
break;
case SMARTAUTOOFFLINEENABLE:
con->smartautoofflineenable = TRUE;
break;
case SMARTAUTOOFFLINEDISABLE:
con->smartautoofflinedisable = TRUE;
break;
case SMARTEXEOFFIMMEDIATE:
con->smartexeoffimmediate = TRUE;
con->testcase=OFFLINE_FULL_SCAN;
break;
case SMARTSHORTSELFTEST :
con->smartshortselftest = TRUE;
con->testcase=SHORT_SELF_TEST;
break;
case SMARTEXTENDSELFTEST :
con->smartextendselftest = TRUE;
con->testcase=EXTEND_SELF_TEST;
break;
case SMARTSHORTCAPSELFTEST:
con->smartshortcapselftest = TRUE;
con->testcase=SHORT_CAPTIVE_SELF_TEST;
break;
case SMARTEXTENDCAPSELFTEST:
con->smartextendcapselftest = TRUE;
con->testcase=EXTEND_CAPTIVE_SELF_TEST;
break;
case SMARTSELFTESTABORT:
con->smartselftestabort = TRUE;
con->testcase=ABORT_SELF_TEST;
break;
case 'h':
case '?':
default:
con->veryquietmode=FALSE;
printslogan();
if (optopt){
pout("=======> UNRECOGNIZED OPTION: %c <=======\n\n",(int)optopt);
Usage();
exit(FAILCMD);
}
Usage();
exit(0);
}
}
// 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();
Usage();
printf ("\nERROR: smartctl can only run a single test (or abort) at a time.\n\n");
exit(FAILCMD);
}
// From here on, normal operations...
printslogan();
// Print Copyright/License info if needed
if (printcopyleft){
printcopy();
if (argc==2)
exit(0);
}
}
// 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);
return;
}
/* Main Program */
int main (int argc, char **argv){
int fd,retval=0;
char *device;
atamainctrl control;
const char *devroot="/dev/";
// define control block for external functions
con=&control;
// Part input arguments
ParseOpts(argc,argv);
// Further argument checking
if (argc != 3){
Usage();
return FAILCMD;
}
// open device - read-only mode is enough to issue needed commands
fd = open(device=argv[2], O_RDONLY);
if (fd<0) {
perror("Smartctl device open failed");
return FAILDEV;
}
// if necessary, try to guess if this is an ATA or SCSI device
if (!tryata && !tryscsi) {
if (!strncmp(device,devroot,strlen(devroot)) && strlen(device)>5){
if (device[5] == 'h')
tryata=1;
if (device[5] == 's')
tryscsi=1;
}
else if (strlen(device)){
if (device[0] == 'h')
tryata=1;
if (device[0] == 's')
tryscsi=1;
}
}
// now call appropriate ATA or SCSI routine
if (tryata)
retval=ataPrintMain(fd);
else if (tryscsi)
scsiPrintMain (fd);
else {
pout("Smartctl: specify if this is an ATA or SCSI device with the -%c or -%c options respectively.\n",
NOTSCSIDEVICE, NOTATADEVICE);
Usage();
return FAILCMD;
}
return retval;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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