Skip to content
Snippets Groups Projects
Commit cd4e9dc1 authored by ballen4705's avatar ballen4705
Browse files

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.


git-svn-id: https://smartmontools.svn.sourceforge.net/svnroot/smartmontools/trunk@88 4ea69e1a-61f1-4043-bf83-b5c94c648137
parent bc8f57a5
Branches
No related tags found
No related merge requests found
CHANGELOG for smartmontools
$Id: CHANGELOG,v 1.14 2002/10/22 16:49:15 ballen4705 Exp $
$Id: CHANGELOG,v 1.15 2002/10/23 12:24:23 ballen4705 Exp $
Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net>
......@@ -29,9 +29,25 @@ NOTES FOR NEXT RELEASE:
smartmontools-5.0-11
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. I may add some additional values as time goes on,
so this is prelimiary.
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.
......@@ -43,7 +59,7 @@ smartmontools-5.0-11
attribute has currently failed or has ever failed.
-p option now prints out license info and CVS strings for all
modules in the code.
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
......
......@@ -110,6 +110,8 @@ v Prints only the vendor specific S.M.A.R.T. attributes & thresholds
l Prints only the S.M.A.R.T. error log
L Prints only the S.M.A.R.T. self-test log
a Prints all parameters for i,c,g,v,t,l,L
q Quiet operation; only show errors in error log, or self-test log, or smart status
Q Very quiet operation: only output is via the returned status
Modify Display for Vendor-specific S.M.A.R.T. Raw Attribute Data:
m Converts Raw Attribute-009 from minutes to hours (Hitachi)
......@@ -183,4 +185,4 @@ Fax: (408) 867-2115
E-Mail: 250-1752@mcimail.com.
$Id: README,v 1.7 2002/10/16 18:54:06 ballen4705 Exp $
$Id: README,v 1.8 2002/10/23 12:24:23 ballen4705 Exp $
......@@ -30,7 +30,7 @@
#include <errno.h>
#include "atacmds.h"
const char *CVSid1="$Id: atacmds.c,v 1.18 2002/10/22 14:57:43 ballen4705 Exp $\n" "\t" CVSID1 ;
const char *CVSid1="$Id: atacmds.c,v 1.19 2002/10/23 12:24:24 ballen4705 Exp $\n" "\t" CVSID1 ;
// 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
......@@ -121,7 +121,7 @@ const int actual_ver[] = {
// Used to warn users about invalid checksums. However we will not
// abort on invalid checksums.
void checksumwarning(const char *string){
printf("Warning! %s error: invalid checksum.\n",string);
pout("Warning! %s error: invalid checksum.\n",string);
fprintf(stderr,"Warning! %s error: invalid checksum.\n",string);
syslog(LOG_INFO,"Warning! %s error: invalid checksum.\n",string);
return;
......@@ -504,7 +504,7 @@ int ataSmartStatus2(int device){
parms[5]=normal_cyl_hi;
if (ioctl(device,HDIO_DRIVE_TASK,parms)){
perror ("SMART Status command failed.");
perror("SMART Status command failed");
return -1;
}
......@@ -517,16 +517,16 @@ int ataSmartStatus2(int device){
return 1;
// We haven't gotten output that makes sense; print out some debugging info
perror("SMART Status command failed:");
printf("Please get assistance from %s\n",PROJECTHOME);
printf("Register values returned from SMART Status command are:\n");
printf("CMD=0x%02x\n",parms[0]);
printf("FR =0x%02x\n",parms[1]);
printf("NS =0x%02x\n",parms[2]);
printf("SC =0x%02x\n",parms[3]);
printf("CL =0x%02x\n",parms[4]);
printf("CH =0x%02x\n",parms[5]);
printf("SEL=0x%02x\n",parms[6]);
perror("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",parms[0]);
pout("FR =0x%02x\n",parms[1]);
pout("NS =0x%02x\n",parms[2]);
pout("SC =0x%02x\n",parms[3]);
pout("CL =0x%02x\n",parms[4]);
pout("CH =0x%02x\n",parms[5]);
pout("SEL=0x%02x\n",parms[6]);
return -1;
}
......@@ -557,13 +557,13 @@ int ataSmartTest(int device, int testtype){
sprintf(cmdmsg,"Abort SMART off-line mode self-test routine");
else
sprintf(cmdmsg,"Execute SMART %s routine immediately in %s mode",type,captive);
printf("Sending command: \"%s\".\n",cmdmsg);
pout("Sending command: \"%s\".\n",cmdmsg);
// Now send the command to test
errornum=ioctl(device, HDIO_DRIVE_CMD, parms);
if (!(errornum && errno==EIO && (testtype=SHORT_CAPTIVE_SELF_TEST || testtype==EXTEND_CAPTIVE_SELF_TEST))){
char errormsg[128];
sprintf(errormsg,"Command \"%s\" failed.",cmdmsg);
sprintf(errormsg,"Command \"%s\" failed",cmdmsg);
perror(errormsg);
fprintf(stderr,"\n");
return -1;
......@@ -571,9 +571,9 @@ int ataSmartTest(int device, int testtype){
// Since the command succeeded, tell user
if (testtype==ABORT_SELF_TEST)
printf("Self-testing aborted!\n");
pout("Self-testing aborted!\n");
else
printf("Drive command \"%s\" successful.\nTesting has begun.\n",cmdmsg);
pout("Drive command \"%s\" successful.\nTesting has begun.\n",cmdmsg);
return 0;
}
......
......@@ -30,7 +30,7 @@
#include <errno.h>
#include "atacmds.h"
const char *CVSid1="$Id: atacmds.cpp,v 1.18 2002/10/22 14:57:43 ballen4705 Exp $\n" "\t" CVSID1 ;
const char *CVSid1="$Id: atacmds.cpp,v 1.19 2002/10/23 12:24:24 ballen4705 Exp $\n" "\t" CVSID1 ;
// 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
......@@ -121,7 +121,7 @@ const int actual_ver[] = {
// Used to warn users about invalid checksums. However we will not
// abort on invalid checksums.
void checksumwarning(const char *string){
printf("Warning! %s error: invalid checksum.\n",string);
pout("Warning! %s error: invalid checksum.\n",string);
fprintf(stderr,"Warning! %s error: invalid checksum.\n",string);
syslog(LOG_INFO,"Warning! %s error: invalid checksum.\n",string);
return;
......@@ -504,7 +504,7 @@ int ataSmartStatus2(int device){
parms[5]=normal_cyl_hi;
if (ioctl(device,HDIO_DRIVE_TASK,parms)){
perror ("SMART Status command failed.");
perror("SMART Status command failed");
return -1;
}
......@@ -517,16 +517,16 @@ int ataSmartStatus2(int device){
return 1;
// We haven't gotten output that makes sense; print out some debugging info
perror("SMART Status command failed:");
printf("Please get assistance from %s\n",PROJECTHOME);
printf("Register values returned from SMART Status command are:\n");
printf("CMD=0x%02x\n",parms[0]);
printf("FR =0x%02x\n",parms[1]);
printf("NS =0x%02x\n",parms[2]);
printf("SC =0x%02x\n",parms[3]);
printf("CL =0x%02x\n",parms[4]);
printf("CH =0x%02x\n",parms[5]);
printf("SEL=0x%02x\n",parms[6]);
perror("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",parms[0]);
pout("FR =0x%02x\n",parms[1]);
pout("NS =0x%02x\n",parms[2]);
pout("SC =0x%02x\n",parms[3]);
pout("CL =0x%02x\n",parms[4]);
pout("CH =0x%02x\n",parms[5]);
pout("SEL=0x%02x\n",parms[6]);
return -1;
}
......@@ -557,13 +557,13 @@ int ataSmartTest(int device, int testtype){
sprintf(cmdmsg,"Abort SMART off-line mode self-test routine");
else
sprintf(cmdmsg,"Execute SMART %s routine immediately in %s mode",type,captive);
printf("Sending command: \"%s\".\n",cmdmsg);
pout("Sending command: \"%s\".\n",cmdmsg);
// Now send the command to test
errornum=ioctl(device, HDIO_DRIVE_CMD, parms);
if (!(errornum && errno==EIO && (testtype=SHORT_CAPTIVE_SELF_TEST || testtype==EXTEND_CAPTIVE_SELF_TEST))){
char errormsg[128];
sprintf(errormsg,"Command \"%s\" failed.",cmdmsg);
sprintf(errormsg,"Command \"%s\" failed",cmdmsg);
perror(errormsg);
fprintf(stderr,"\n");
return -1;
......@@ -571,9 +571,9 @@ int ataSmartTest(int device, int testtype){
// Since the command succeeded, tell user
if (testtype==ABORT_SELF_TEST)
printf("Self-testing aborted!\n");
pout("Self-testing aborted!\n");
else
printf("Drive command \"%s\" successful.\nTesting has begun.\n",cmdmsg);
pout("Drive command \"%s\" successful.\nTesting has begun.\n",cmdmsg);
return 0;
}
......
......@@ -26,7 +26,7 @@
#define _ATACMDS_H_
#ifndef CVSID1
#define CVSID1 "$Id: atacmds.h,v 1.16 2002/10/22 14:57:43 ballen4705 Exp $\n"
#define CVSID1 "$Id: atacmds.h,v 1.17 2002/10/23 12:24:24 ballen4705 Exp $\n"
#endif
// These are the major and minor versions for smartd and smartctl
......@@ -373,4 +373,11 @@ int ataSmartTest(int device, int testtype);
int TestTime(struct ata_smart_values data,int testtype);
// like printf() except that we can control it better....
void pout(char *fmt, ...);
// MACROS to control printing behavior
#define QUIETON {if (quietmode) veryquietmode=0;}
#define QUIETOFF {if (quietmode && !veryquietmode) veryquietmode=1;}
#endif /* _ATACMDS_H_ */
This diff is collapsed.
This diff is collapsed.
......@@ -26,7 +26,7 @@
#define _SMART_PRINT_H_
#ifndef CVSID2
#define CVSID2 "$Id: ataprint.h,v 1.10 2002/10/22 20:35:42 ballen4705 Exp $\n"
#define CVSID2 "$Id: ataprint.h,v 1.11 2002/10/23 12:24:24 ballen4705 Exp $\n"
#endif
#include <stdio.h>
......@@ -49,7 +49,8 @@ void PrintSmartAttribWithThres (struct ata_smart_values data,
struct ata_smart_thresholds thresholds,
int onlyfailed);
void ataPrintSmartSelfTestlog(struct ata_smart_selftestlog data, int allentries);
// returns number of entries that had logged errors
int ataPrintSmartSelfTestlog(struct ata_smart_selftestlog data, int allentries);
void ataPseudoCheckSmart (struct ata_smart_values ,
struct ata_smart_thresholds );
......
......@@ -27,7 +27,7 @@
#ifndef CVSID3
#define CVSID3 "$Id: extern.h,v 1.7 2002/10/22 09:44:55 ballen4705 Exp $\n"
#define CVSID3 "$Id: extern.h,v 1.8 2002/10/23 12:24:24 ballen4705 Exp $\n"
#endif
extern unsigned char driveinfo;
......@@ -51,4 +51,6 @@ extern unsigned char smartautosaveenable;
extern unsigned char smartautosavedisable;
extern unsigned char smart009minutes;
extern int testcase;
extern unsigned char quietmode;
extern unsigned char veryquietmode;
#endif
\# Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net>
\#
\# $Id: smartctl.8,v 1.14 2002/10/22 16:49:16 ballen4705 Exp $
\# $Id: smartctl.8,v 1.15 2002/10/23 12:24:24 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
......@@ -15,11 +15,11 @@
\# 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: 2002/10/22 16:49:16 $" "smartmontools-5.0"
.TH SMARTCTL 8 "$Date: 2002/10/23 12:24:24 $" "smartmontools-5.0"
.SH NAME
smartctl \- S.M.A.R.T. control utility
.SH SYNOPSIS
.B smartctl \-[piaedtTfFcgvlLm[O|S|s|X|x|A]] device
.B smartctl \-[piqQaedtTfFcgvlLm[O|S|s|X|x|A]] device
.SH DESCRIPTION
.B smartctl
......@@ -34,7 +34,11 @@ below)
.B smartctl
is a command line utility designed to perform S.M.A.R.T. tasks such as
printing the S.M.A.R.T. self-test and error logs, and enabling and
disabling S.M.A.R.T. automatic testing.
disabling S.M.A.R.T. automatic testing. Note: if the user issues a
S.M.A.R.T. command that is (apparently) not implemented by the device,
we print a warning message but issue the command anyway. This should
not cause problems: unimplemented S.M.A.R.T. commands issued to a
drive are ignored and return an error.
.B smartctl
also provides limited TapeAlerts support for some SCSI tape drives and
......@@ -81,6 +85,21 @@ firmware version, and ATA Standard version/revision information.
Says if the device supports S.M.A.R.T., and if so, whether
S.M.A.R.T. support is currently enabled or disabled.
.TP
.B q
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.
.TP
.B Q
Very Quiet mode: Print no ouput. The only way to learn about what was
found is to use the exit status of
.B smartctl
(see RETURN VALUES below).
.TP
.B a
All: Prints all parameters for c,i,g,v,t,l,L (for SCSI c,i). This prints all
S.M.A.R.T. information about the disk.
......@@ -317,16 +336,35 @@ internally in minutes rather than hours.
.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. Bit 0: Command line did not parse. Bit 1:
Device open failed. Bit 2: SMART command to disk failed. Bit 3:
SMART status check returned "DISK FAILING". Bit 4: SMART status check
returned "DISK OK" but we found prefail attributes <= threshold. Bit
5: SMART status check returned "DISK OK" but we found that some (usage
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.
.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. Bit 6: Unable to get Device IDENTITY information.
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.
.PP
.SH AUTHOR
Bruce Allen
......@@ -401,4 +439,4 @@ 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.14 2002/10/22 16:49:16 ballen4705 Exp $
$Id: smartctl.8,v 1.15 2002/10/23 12:24:24 ballen4705 Exp $
......@@ -30,6 +30,7 @@
#include <sys/fcntl.h>
#include <sys/types.h>
#include <string.h>
#include <stdarg.h>
#include "smartctl.h"
#include "atacmds.h"
#include "ataprint.h"
......@@ -37,7 +38,7 @@
#include "scsiprint.h"
extern const char *CVSid1, *CVSid2, *CVSid4, *CVSid5;
const char* CVSid6="$Id: smartctl.c,v 1.14 2002/10/22 16:49:16 ballen4705 Exp $\n"
const char* CVSid6="$Id: smartctl.c,v 1.15 2002/10/23 12:24:24 ballen4705 Exp $\n"
"\t" CVSID1 "\t" CVSID2 "\t" CVSID4 "\t" CVSID5 "\t" CVSID6 ;
unsigned char driveinfo = FALSE;
......@@ -61,14 +62,99 @@ unsigned char smartautosaveenable = FALSE;
unsigned char smartautosavedisable = FALSE;
unsigned char printcopyleft = FALSE;
unsigned char smart009minutes = FALSE;
unsigned char quietmode = FALSE;
unsigned char veryquietmode = FALSE;
int testcase = -1;
/* void Usage (void)
prints help information for command syntax */
void printslogan(){
pout("smartctl version %d.%d-%d Copyright (C) 2002 Bruce Allen\n",RELEASE_MAJOR,RELEASE_MINOR,SMARTMONTOOLS_VERSION);
pout("Home page of smartctl is %s\n\n",PROJECTHOME);
return;
}
int massagecvs(char *out,const char *in){
char filename[128], version[128], date[128];
int i=0;
const char *savein=in;
// skip to I of $Id:
while (*in !='\0' && *in!='I')
in++;
// skip to start of filename
if (!*in)
return 0;
in+=4;
// copy filename
i=0;
while (i<100 && *in!=',' && *in)
filename[i++]=*in++;
filename[i]='\0';
if (!*in)
return 0;
// skip ,v and space
in+=3;
i=0;
// copy version number
while (i<100 && *in!=' ' && *in)
version[i++]=*in++;
version[i]='\0';
if (!*in)
return 0;
// skip space
in++;
// copy date
i=0;
while (i<100 && *in!=' ' && *in)
date[i++]=*in++;
date[i]='\0';
sprintf(out,"%-13s revision: %-6s date: %-15s", filename, version, date);
return in-savein;
}
// prints a single set of CVS ids
void printone(const char *cvsid){
char strings[512];
const char *here;
int len,line=1;
here=cvsid;
while ((len=massagecvs(strings,here))){
switch (line++){
case 1:
pout("Module:");
break;
default:
pout(" uses:");
}
pout(" %s\n",strings);
here+=len;
}
return;
}
void printcopy(){
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(CVSid6);
printone(CVSid1);
printone(CVSid2);
printone(CVSid4);
printone(CVSid5);
return;
}
/* void prints help information for command syntax */
void Usage ( void){
printf( "Usage: smartctl -[options] [device]\n\n");
printf( "Read Only Options:\n");
......@@ -80,6 +166,8 @@ void Usage ( void){
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( "\t\t%c\t\tQuiet: only show SMART drive errors (ATA Only)\n", QUIETMODE);
printf( "\t\t%c\t\tVery Quiet: no display, use exit status (ATA Only)\n", VERYQUIETMODE);
printf( "\n");
printf( "Vendor-specific Display Options:\n");
printf( "\t\t%c\t\tRaw Attribute 009 is minutes (ATA Only)\n", SMART009MINUTES);
......@@ -104,7 +192,6 @@ void Usage ( void){
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\n");
printf("Please see the man pages or %s for further information.\n",PROJECTHOME);
}
const char opts[] = {
......@@ -113,7 +200,7 @@ const char opts[] = {
SMARTENABLE, SMARTAUTOOFFLINEENABLE, SMARTAUTOOFFLINEDISABLE,
SMARTEXEOFFIMMEDIATE, SMARTSHORTSELFTEST, SMARTEXTENDSELFTEST,
SMARTSHORTCAPSELFTEST, SMARTEXTENDCAPSELFTEST, SMARTSELFTESTABORT,
SMARTAUTOSAVEENABLE,SMARTAUTOSAVEDISABLE,PRINTCOPYLEFT,SMART009MINUTES,'\0'
SMARTAUTOSAVEENABLE,SMARTAUTOSAVEDISABLE,PRINTCOPYLEFT,SMART009MINUTES,QUIETMODE,VERYQUIETMODE,'\0'
};
/* Takes command options and sets features to be run */
......@@ -125,6 +212,14 @@ void ParseOpts (int argc, char** argv){
opterr=1;
while (-1 != (optchar = getopt(argc, argv, opts))) {
switch (optchar){
case QUIETMODE:
quietmode=TRUE;
veryquietmode=TRUE;
break;
case VERYQUIETMODE:
quietmode=FALSE;
veryquietmode=TRUE;
break;
case SMART009MINUTES:
smart009minutes=TRUE;
break;
......@@ -200,43 +295,60 @@ void ParseOpts (int argc, char** argv){
testcase=ABORT_SELF_TEST;
break;
default:
veryquietmode=FALSE;
printslogan();
Usage();
exit(FAILCMD);
}
if ( (smartexeoffimmediate + smartshortselftest +
smartextendselftest + smartshortcapselftest +
smartextendcapselftest +smartselftestabort ) > 1){
}
// error message if user has asked for more than one test
if (1<(smartexeoffimmediate+smartshortselftest+smartextendselftest+
smartshortcapselftest+smartextendcapselftest+smartselftestabort)){
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);
}
}
/* Main Program */
// Printing function (controlled by global veryquietmode)
void pout(char *fmt, ...){
va_list ap;
// initialize variable argument list
va_start(ap,fmt);
if (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;
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",PROJECTHOME);
// Part input arguments
ParseOpts(argc,argv);
// Print Copyright/License info if needed
if (printcopyleft){
printf("\nsmartctl 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 IDs of files used to build this code are:\n%s%s%s%s%s",CVSid1,CVSid2,CVSid4,CVSid5,CVSid6);
if (argc==2)
return 0;
}
// Further argument checking
if (argc != 3){
Usage();
......@@ -247,7 +359,7 @@ int main (int argc, char **argv){
fd = open(device=argv[2], O_RDONLY);
if (fd<0) {
perror ("Smartctl device open failed:");
perror("Smartctl device open failed");
return FAILDEV;
}
......
......@@ -30,6 +30,7 @@
#include <sys/fcntl.h>
#include <sys/types.h>
#include <string.h>
#include <stdarg.h>
#include "smartctl.h"
#include "atacmds.h"
#include "ataprint.h"
......@@ -37,7 +38,7 @@
#include "scsiprint.h"
extern const char *CVSid1, *CVSid2, *CVSid4, *CVSid5;
const char* CVSid6="$Id: smartctl.cpp,v 1.14 2002/10/22 16:49:16 ballen4705 Exp $\n"
const char* CVSid6="$Id: smartctl.cpp,v 1.15 2002/10/23 12:24:24 ballen4705 Exp $\n"
"\t" CVSID1 "\t" CVSID2 "\t" CVSID4 "\t" CVSID5 "\t" CVSID6 ;
unsigned char driveinfo = FALSE;
......@@ -61,14 +62,99 @@ unsigned char smartautosaveenable = FALSE;
unsigned char smartautosavedisable = FALSE;
unsigned char printcopyleft = FALSE;
unsigned char smart009minutes = FALSE;
unsigned char quietmode = FALSE;
unsigned char veryquietmode = FALSE;
int testcase = -1;
/* void Usage (void)
prints help information for command syntax */
void printslogan(){
pout("smartctl version %d.%d-%d Copyright (C) 2002 Bruce Allen\n",RELEASE_MAJOR,RELEASE_MINOR,SMARTMONTOOLS_VERSION);
pout("Home page of smartctl is %s\n\n",PROJECTHOME);
return;
}
int massagecvs(char *out,const char *in){
char filename[128], version[128], date[128];
int i=0;
const char *savein=in;
// skip to I of $Id:
while (*in !='\0' && *in!='I')
in++;
// skip to start of filename
if (!*in)
return 0;
in+=4;
// copy filename
i=0;
while (i<100 && *in!=',' && *in)
filename[i++]=*in++;
filename[i]='\0';
if (!*in)
return 0;
// skip ,v and space
in+=3;
i=0;
// copy version number
while (i<100 && *in!=' ' && *in)
version[i++]=*in++;
version[i]='\0';
if (!*in)
return 0;
// skip space
in++;
// copy date
i=0;
while (i<100 && *in!=' ' && *in)
date[i++]=*in++;
date[i]='\0';
sprintf(out,"%-13s revision: %-6s date: %-15s", filename, version, date);
return in-savein;
}
// prints a single set of CVS ids
void printone(const char *cvsid){
char strings[512];
const char *here;
int len,line=1;
here=cvsid;
while ((len=massagecvs(strings,here))){
switch (line++){
case 1:
pout("Module:");
break;
default:
pout(" uses:");
}
pout(" %s\n",strings);
here+=len;
}
return;
}
void printcopy(){
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(CVSid6);
printone(CVSid1);
printone(CVSid2);
printone(CVSid4);
printone(CVSid5);
return;
}
/* void prints help information for command syntax */
void Usage ( void){
printf( "Usage: smartctl -[options] [device]\n\n");
printf( "Read Only Options:\n");
......@@ -80,6 +166,8 @@ void Usage ( void){
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( "\t\t%c\t\tQuiet: only show SMART drive errors (ATA Only)\n", QUIETMODE);
printf( "\t\t%c\t\tVery Quiet: no display, use exit status (ATA Only)\n", VERYQUIETMODE);
printf( "\n");
printf( "Vendor-specific Display Options:\n");
printf( "\t\t%c\t\tRaw Attribute 009 is minutes (ATA Only)\n", SMART009MINUTES);
......@@ -104,7 +192,6 @@ void Usage ( void){
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\n");
printf("Please see the man pages or %s for further information.\n",PROJECTHOME);
}
const char opts[] = {
......@@ -113,7 +200,7 @@ const char opts[] = {
SMARTENABLE, SMARTAUTOOFFLINEENABLE, SMARTAUTOOFFLINEDISABLE,
SMARTEXEOFFIMMEDIATE, SMARTSHORTSELFTEST, SMARTEXTENDSELFTEST,
SMARTSHORTCAPSELFTEST, SMARTEXTENDCAPSELFTEST, SMARTSELFTESTABORT,
SMARTAUTOSAVEENABLE,SMARTAUTOSAVEDISABLE,PRINTCOPYLEFT,SMART009MINUTES,'\0'
SMARTAUTOSAVEENABLE,SMARTAUTOSAVEDISABLE,PRINTCOPYLEFT,SMART009MINUTES,QUIETMODE,VERYQUIETMODE,'\0'
};
/* Takes command options and sets features to be run */
......@@ -125,6 +212,14 @@ void ParseOpts (int argc, char** argv){
opterr=1;
while (-1 != (optchar = getopt(argc, argv, opts))) {
switch (optchar){
case QUIETMODE:
quietmode=TRUE;
veryquietmode=TRUE;
break;
case VERYQUIETMODE:
quietmode=FALSE;
veryquietmode=TRUE;
break;
case SMART009MINUTES:
smart009minutes=TRUE;
break;
......@@ -200,43 +295,60 @@ void ParseOpts (int argc, char** argv){
testcase=ABORT_SELF_TEST;
break;
default:
veryquietmode=FALSE;
printslogan();
Usage();
exit(FAILCMD);
}
if ( (smartexeoffimmediate + smartshortselftest +
smartextendselftest + smartshortcapselftest +
smartextendcapselftest +smartselftestabort ) > 1){
}
// error message if user has asked for more than one test
if (1<(smartexeoffimmediate+smartshortselftest+smartextendselftest+
smartshortcapselftest+smartextendcapselftest+smartselftestabort)){
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);
}
}
/* Main Program */
// Printing function (controlled by global veryquietmode)
void pout(char *fmt, ...){
va_list ap;
// initialize variable argument list
va_start(ap,fmt);
if (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;
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",PROJECTHOME);
// Part input arguments
ParseOpts(argc,argv);
// Print Copyright/License info if needed
if (printcopyleft){
printf("\nsmartctl 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 IDs of files used to build this code are:\n%s%s%s%s%s",CVSid1,CVSid2,CVSid4,CVSid5,CVSid6);
if (argc==2)
return 0;
}
// Further argument checking
if (argc != 3){
Usage();
......@@ -247,7 +359,7 @@ int main (int argc, char **argv){
fd = open(device=argv[2], O_RDONLY);
if (fd<0) {
perror ("Smartctl device open failed:");
perror("Smartctl device open failed");
return FAILDEV;
}
......
......@@ -26,7 +26,7 @@
#define __SMARTCTL_H_
#ifndef CVSID6
#define CVSID6 "$Id: smartctl.h,v 1.8 2002/10/22 16:49:16 ballen4705 Exp $\n"
#define CVSID6 "$Id: smartctl.h,v 1.9 2002/10/23 12:24:24 ballen4705 Exp $\n"
#endif
/* Defines for command line options */
......@@ -51,6 +51,8 @@
#define SMARTAUTOSAVEDISABLE 'F'
#define PRINTCOPYLEFT 'p'
#define SMART009MINUTES 'm'
#define QUIETMODE 'q'
#define VERYQUIETMODE 'Q'
/* Boolean Values */
......@@ -62,8 +64,9 @@
// command line did not parse
#define FAILCMD (0x01<<0)
// device open failed
// device open failed or could not get identity info
#define FAILDEV (0x01<<1)
#define FAILID (0x01<<1)
// smart command failed
#define FAILSMART (0x01<<2)
......@@ -78,7 +81,10 @@
// attributes have failed in the past
#define FAILAGE (0x01<<5)
// Device ID failed
#define FAILID (0x01<<6)
// Device had Errors in the error log
#define FAILERR (0x01<<6)
// Device had Errors in the self-test log
#define FAILLOG (0x01<<7)
#endif
......@@ -36,7 +36,7 @@
#include "smartd.h"
extern const char *CVSid1, *CVSid2;
const char *CVSid3="$Id: smartd.c,v 1.13 2002/10/22 14:57:43 ballen4705 Exp $\n"
const char *CVSid3="$Id: smartd.c,v 1.14 2002/10/23 12:24:24 ballen4705 Exp $\n"
"\t" CVSID1 "\t" CVSID4 "\t" CVSID7 ;
int daemon_init(void){
......@@ -70,6 +70,22 @@ void printout(int priority,char *fmt, ...){
return;
}
// Printing function for atacmds
void pout(char *fmt, ...){
va_list ap;
// initialize variable argument list
va_start(ap,fmt);
va_end(ap);
return;
#if (0)
// print out
vprintf(fmt,ap);
va_end(ap);
return;
#endif
}
/* prints help information for command syntax */
void Usage ( void){
printout(LOG_INFO,"smartd version %d.%d-%d - S.M.A.R.T. Daemon\n",
......
......@@ -36,7 +36,7 @@
#include "smartd.h"
extern const char *CVSid1, *CVSid2;
const char *CVSid3="$Id: smartd.cpp,v 1.13 2002/10/22 14:57:43 ballen4705 Exp $\n"
const char *CVSid3="$Id: smartd.cpp,v 1.14 2002/10/23 12:24:24 ballen4705 Exp $\n"
"\t" CVSID1 "\t" CVSID4 "\t" CVSID7 ;
int daemon_init(void){
......@@ -70,6 +70,22 @@ void printout(int priority,char *fmt, ...){
return;
}
// Printing function for atacmds
void pout(char *fmt, ...){
va_list ap;
// initialize variable argument list
va_start(ap,fmt);
va_end(ap);
return;
#if (0)
// print out
vprintf(fmt,ap);
va_end(ap);
return;
#endif
}
/* prints help information for command syntax */
void Usage ( void){
printout(LOG_INFO,"smartd version %d.%d-%d - S.M.A.R.T. Daemon\n",
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment