diff --git a/sm5/CHANGELOG b/sm5/CHANGELOG index e5840e53ed44572f8d7f5c382cf042520aaa229b..3568405cb812b83f332f43a1991933b237b33e57 100644 --- a/sm5/CHANGELOG +++ b/sm5/CHANGELOG @@ -1,6 +1,6 @@ CHANGELOG for smartmontools -$Id: CHANGELOG,v 1.96 2003/02/24 15:51:30 ballen4705 Exp $ +$Id: CHANGELOG,v 1.97 2003/03/06 06:28:46 ballen4705 Exp $ Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net> @@ -33,6 +33,12 @@ NOTES FOR FUTURE RELEASES: see TODO file. CURRENT RELEASE (see VERSION file in this directory): + [BA] smartd: Added -r ID and -R ID for reporting/tracking Raw + values of Attributes. + + [BA] smartd/smartctl: Changed printing of spin-up-time attribute + raw value to reflect current/average as per IBM standard. + [BA] smartd/smartctl: Added -v 9,seconds option for disks which use Attribute 9 for power-on lifetime in seconds. diff --git a/sm5/atacmds.c b/sm5/atacmds.c index f3d90127f59de5d60f1da36a88980929699cf9d0..8bf8d8f89d4e8068931c3ca3091a0c349e8ef8e4 100644 --- a/sm5/atacmds.c +++ b/sm5/atacmds.c @@ -30,7 +30,7 @@ #include "atacmds.h" #include "utility.h" -const char *atacmds_c_cvsid="$Id: atacmds.c,v 1.54 2003/02/24 15:51:31 ballen4705 Exp $" ATACMDS_H_CVSID UTILITY_H_CVSID; +const char *atacmds_c_cvsid="$Id: atacmds.c,v 1.55 2003/03/06 06:28:47 ballen4705 Exp $" ATACMDS_H_CVSID UTILITY_H_CVSID; // 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 @@ -782,6 +782,88 @@ int ataCheckAttribute(struct ata_smart_values *data, return -1*(disk->id); } + +// This routine prints the raw value of an attribute as a text string +// into out. It also returns this 48-bit number as a long long. The +// array defs[] contains non-zero values if particular attributes have +// non-default interpretations. + +long long ataPrintSmartAttribRawValue(char *out, + struct ata_smart_attribute *attribute, + unsigned char *defs){ + long long rawvalue; + int j; + + // convert the six individual bytes to a long long (8 byte) integer. + // This is the value that we'll eventually return. + rawvalue = 0; + for (j=0; j<6; j++) { + // This looks a bit roundabout, but is necessary. Don't + // succumb to the temptation to use raw[j]<<(8*j) since under + // the normal rules this will be promoted to the native type. + // On a 32 bit machine this might then overflow. + long long temp; + temp = attribute->raw[j]; + temp <<= 8*j; + rawvalue |= temp; + } + + // This switch statement is where we handle Raw attributes + // that are stored in an unusual vendor-specific format, + switch (attribute->id){ + // Spin-up time + case 3: + { + int i, spin[2]; + // construct two twy-byte quantities, print first + for (i=0; i<2; i++){ + spin[i] = attribute->raw[2*i+1]; + spin[i] <<= 8; + spin[i] |= attribute->raw[2*i]; + } + out+=sprintf(out, "%d", spin[0]); + + // if second nonzero then it stores the average spin-up time + if (spin[1]) + sprintf(out, " (Average %d)", spin[1]); + } + break; + // Power on time + case 9: + if (defs[9]==1){ + // minutes + long long tmp1=rawvalue/60; + long long tmp2=rawvalue%60; + sprintf(out, "%lluh+%02llum", tmp1, tmp2); + } + else if (defs[9]==3){ + // seconds + long long hours=rawvalue/3600; + long long minutes=(rawvalue-3600*hours)/60; + long long seconds=rawvalue%60; + sprintf(out, "%lluh+%02llum+%02llus", hours, minutes, seconds); + } + else + // hours + sprintf(out, "%llu", rawvalue); //stored in hours + break; + // Temperature + case 194: + out+=sprintf(out, "%d", (int)attribute->raw[0]); + if (!(rawvalue==attribute->raw[0])) + // The other bytes are in use. Try IBM's model + sprintf(out, " (Lifetime Min/Max %d/%d)",(int)attribute->raw[2], + (int)attribute->raw[4]); + break; + default: + sprintf(out, "%llu", rawvalue); + } + + // Return the full value + return rawvalue; +} + + // Note some attribute names appear redundant because different // manufacturers use different attribute IDs for an attribute with the // same name. The array defs[] contains non-zero values if particular diff --git a/sm5/atacmds.cpp b/sm5/atacmds.cpp index 19578e85fb56cec371636223505726dfdbb9234b..3f4b4b0327768ea46f25c69e5c872f9c717a10ff 100644 --- a/sm5/atacmds.cpp +++ b/sm5/atacmds.cpp @@ -30,7 +30,7 @@ #include "atacmds.h" #include "utility.h" -const char *atacmds_c_cvsid="$Id: atacmds.cpp,v 1.54 2003/02/24 15:51:31 ballen4705 Exp $" ATACMDS_H_CVSID UTILITY_H_CVSID; +const char *atacmds_c_cvsid="$Id: atacmds.cpp,v 1.55 2003/03/06 06:28:47 ballen4705 Exp $" ATACMDS_H_CVSID UTILITY_H_CVSID; // 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 @@ -782,6 +782,88 @@ int ataCheckAttribute(struct ata_smart_values *data, return -1*(disk->id); } + +// This routine prints the raw value of an attribute as a text string +// into out. It also returns this 48-bit number as a long long. The +// array defs[] contains non-zero values if particular attributes have +// non-default interpretations. + +long long ataPrintSmartAttribRawValue(char *out, + struct ata_smart_attribute *attribute, + unsigned char *defs){ + long long rawvalue; + int j; + + // convert the six individual bytes to a long long (8 byte) integer. + // This is the value that we'll eventually return. + rawvalue = 0; + for (j=0; j<6; j++) { + // This looks a bit roundabout, but is necessary. Don't + // succumb to the temptation to use raw[j]<<(8*j) since under + // the normal rules this will be promoted to the native type. + // On a 32 bit machine this might then overflow. + long long temp; + temp = attribute->raw[j]; + temp <<= 8*j; + rawvalue |= temp; + } + + // This switch statement is where we handle Raw attributes + // that are stored in an unusual vendor-specific format, + switch (attribute->id){ + // Spin-up time + case 3: + { + int i, spin[2]; + // construct two twy-byte quantities, print first + for (i=0; i<2; i++){ + spin[i] = attribute->raw[2*i+1]; + spin[i] <<= 8; + spin[i] |= attribute->raw[2*i]; + } + out+=sprintf(out, "%d", spin[0]); + + // if second nonzero then it stores the average spin-up time + if (spin[1]) + sprintf(out, " (Average %d)", spin[1]); + } + break; + // Power on time + case 9: + if (defs[9]==1){ + // minutes + long long tmp1=rawvalue/60; + long long tmp2=rawvalue%60; + sprintf(out, "%lluh+%02llum", tmp1, tmp2); + } + else if (defs[9]==3){ + // seconds + long long hours=rawvalue/3600; + long long minutes=(rawvalue-3600*hours)/60; + long long seconds=rawvalue%60; + sprintf(out, "%lluh+%02llum+%02llus", hours, minutes, seconds); + } + else + // hours + sprintf(out, "%llu", rawvalue); //stored in hours + break; + // Temperature + case 194: + out+=sprintf(out, "%d", (int)attribute->raw[0]); + if (!(rawvalue==attribute->raw[0])) + // The other bytes are in use. Try IBM's model + sprintf(out, " (Lifetime Min/Max %d/%d)",(int)attribute->raw[2], + (int)attribute->raw[4]); + break; + default: + sprintf(out, "%llu", rawvalue); + } + + // Return the full value + return rawvalue; +} + + // Note some attribute names appear redundant because different // manufacturers use different attribute IDs for an attribute with the // same name. The array defs[] contains non-zero values if particular diff --git a/sm5/atacmds.h b/sm5/atacmds.h index 1e4e8eed4d1fc3982e0c052c42e4abe3cc040606..b1094a56155550353e0cea67b0d936f94710d4d8 100644 --- a/sm5/atacmds.h +++ b/sm5/atacmds.h @@ -26,7 +26,7 @@ #define _ATACMDS_H_ #ifndef ATACMDS_H_CVSID -#define ATACMDS_H_CVSID "$Id: atacmds.h,v 1.33 2003/01/17 12:20:24 ballen4705 Exp $\n" +#define ATACMDS_H_CVSID "$Id: atacmds.h,v 1.34 2003/03/06 06:28:47 ballen4705 Exp $\n" #endif // These are the major and minor versions for smartd and smartctl @@ -341,6 +341,12 @@ int ataSmartTest(int device, int testtype); int TestTime(struct ata_smart_values *data,int testtype); +// Prints the raw value (with appropriate formatting) into the +// character string out. +long long ataPrintSmartAttribRawValue(char *out, + struct ata_smart_attribute *attribute, + unsigned char *defs); + // Prints Attribute Name for standard SMART attributes. Writes a // 30 byte string with attribute name into output void ataPrintSmartAttribName(char *output, unsigned char id, unsigned char *defs); diff --git a/sm5/ataprint.c b/sm5/ataprint.c index f63ad77eb040c69931ea656b7d89546a5d0dec45..fc04a0e3685f0f92d026b0b4f91b8ec7e0572dee 100644 --- a/sm5/ataprint.c +++ b/sm5/ataprint.c @@ -33,7 +33,7 @@ #include "extern.h" #include "utility.h" -const char *ataprint_c_cvsid="$Id: ataprint.c,v 1.58 2003/02/24 15:51:32 ballen4705 Exp $" +const char *ataprint_c_cvsid="$Id: ataprint.c,v 1.59 2003/03/06 06:28:47 ballen4705 Exp $" ATACMDS_H_CVSID ATAPRINT_H_CVSID EXTERN_H_CVSID SMARTCTL_H_CVSID UTILITY_H_CVSID; // for passing global control variables @@ -452,9 +452,9 @@ void PrintSmartExtendedSelfTestPollingTime ( struct ata_smart_values *data) void PrintSmartAttribWithThres (struct ata_smart_values *data, struct ata_smart_thresholds *thresholds, int onlyfailed){ - int i,j; - long long rawvalue; + int i; int needheader=1; + char rawstring[64]; // step through all vendor attributes for (i=0; i<NUMBER_ATA_SMART_ATTRIBUTES; i++){ @@ -505,55 +505,10 @@ void PrintSmartAttribWithThres (struct ata_smart_values *data, pout("0x%04x %.3d %.3d %.3d %-9s%-12s", (int)disk->status.all, (int)disk->current, (int)disk->worst, (int)thre->threshold, type, status); - - // convert the six individual bytes to a long long (8 byte) integer - rawvalue = 0; - for (j=0; j<6; j++) { - // This looks a bit roundabout, but is necessary. Don't - // succumb to the temptation to use raw[j]<<(8*j) since under - // the normal rules this will be promoted to the native type. - // On a 32 bit machine this might then overflow. - long long temp; - temp = disk->raw[j]; - temp <<= 8*j; - rawvalue |= temp; - } - // This switch statement is where we handle Raw attributes - // that are stored in an unusual vendor-specific format, - switch (disk->id){ - // Power on time - case 9: - if (con->attributedefs[9]==1){ - // minutes - long long tmp1=rawvalue/60; - long long tmp2=rawvalue%60; - pout("%lluh+%02llum\n", tmp1, tmp2); - } - else if (con->attributedefs[9]==3){ - // seconds - long long hours=rawvalue/3600; - long long minutes=(rawvalue-3600*hours)/60; - long long seconds=rawvalue%60; - pout("%lluh+%02llum+%02llus\n", hours, minutes, seconds); - } - else - // hours - pout("%llu\n", rawvalue); //stored in hours - break; - // Temperature - case 194: - pout("%d", (int)disk->raw[0]); - if (rawvalue==disk->raw[0]) - pout("\n"); - else - // The other bytes are in use. Try IBM's model - pout(" (Lifetime Min/Max %d/%d)\n",(int)disk->raw[2], - (int)disk->raw[4]); - break; - default: - pout("%llu\n", rawvalue); - } + // print raw value of attribute + ataPrintSmartAttribRawValue(rawstring, disk, con->attributedefs); + pout("%s\n", rawstring); // print a warning if there is inconsistency here! if (disk->id != thre->id){ @@ -568,7 +523,6 @@ void PrintSmartAttribWithThres (struct ata_smart_values *data, if (!needheader) pout("\n"); } - void ataPrintGeneralSmartValues(struct ata_smart_values *data){ pout("General SMART Values:\n"); diff --git a/sm5/ataprint.cpp b/sm5/ataprint.cpp index 8fe8b0ef4df80d0b850eabca12d98190b652f25b..b80ef987bacb1238927e5559fc2f1c4409894928 100644 --- a/sm5/ataprint.cpp +++ b/sm5/ataprint.cpp @@ -33,7 +33,7 @@ #include "extern.h" #include "utility.h" -const char *ataprint_c_cvsid="$Id: ataprint.cpp,v 1.58 2003/02/24 15:51:32 ballen4705 Exp $" +const char *ataprint_c_cvsid="$Id: ataprint.cpp,v 1.59 2003/03/06 06:28:47 ballen4705 Exp $" ATACMDS_H_CVSID ATAPRINT_H_CVSID EXTERN_H_CVSID SMARTCTL_H_CVSID UTILITY_H_CVSID; // for passing global control variables @@ -452,9 +452,9 @@ void PrintSmartExtendedSelfTestPollingTime ( struct ata_smart_values *data) void PrintSmartAttribWithThres (struct ata_smart_values *data, struct ata_smart_thresholds *thresholds, int onlyfailed){ - int i,j; - long long rawvalue; + int i; int needheader=1; + char rawstring[64]; // step through all vendor attributes for (i=0; i<NUMBER_ATA_SMART_ATTRIBUTES; i++){ @@ -505,55 +505,10 @@ void PrintSmartAttribWithThres (struct ata_smart_values *data, pout("0x%04x %.3d %.3d %.3d %-9s%-12s", (int)disk->status.all, (int)disk->current, (int)disk->worst, (int)thre->threshold, type, status); - - // convert the six individual bytes to a long long (8 byte) integer - rawvalue = 0; - for (j=0; j<6; j++) { - // This looks a bit roundabout, but is necessary. Don't - // succumb to the temptation to use raw[j]<<(8*j) since under - // the normal rules this will be promoted to the native type. - // On a 32 bit machine this might then overflow. - long long temp; - temp = disk->raw[j]; - temp <<= 8*j; - rawvalue |= temp; - } - // This switch statement is where we handle Raw attributes - // that are stored in an unusual vendor-specific format, - switch (disk->id){ - // Power on time - case 9: - if (con->attributedefs[9]==1){ - // minutes - long long tmp1=rawvalue/60; - long long tmp2=rawvalue%60; - pout("%lluh+%02llum\n", tmp1, tmp2); - } - else if (con->attributedefs[9]==3){ - // seconds - long long hours=rawvalue/3600; - long long minutes=(rawvalue-3600*hours)/60; - long long seconds=rawvalue%60; - pout("%lluh+%02llum+%02llus\n", hours, minutes, seconds); - } - else - // hours - pout("%llu\n", rawvalue); //stored in hours - break; - // Temperature - case 194: - pout("%d", (int)disk->raw[0]); - if (rawvalue==disk->raw[0]) - pout("\n"); - else - // The other bytes are in use. Try IBM's model - pout(" (Lifetime Min/Max %d/%d)\n",(int)disk->raw[2], - (int)disk->raw[4]); - break; - default: - pout("%llu\n", rawvalue); - } + // print raw value of attribute + ataPrintSmartAttribRawValue(rawstring, disk, con->attributedefs); + pout("%s\n", rawstring); // print a warning if there is inconsistency here! if (disk->id != thre->id){ @@ -568,7 +523,6 @@ void PrintSmartAttribWithThres (struct ata_smart_values *data, if (!needheader) pout("\n"); } - void ataPrintGeneralSmartValues(struct ata_smart_values *data){ pout("General SMART Values:\n"); diff --git a/sm5/smartd.8 b/sm5/smartd.8 index 2c510f7fc5b6cd7ade0c874a1aef267cda4a7d34..60c72bf6312a884c8349cef4bee81443a20c6ee3 100644 --- a/sm5/smartd.8 +++ b/sm5/smartd.8 @@ -1,6 +1,6 @@ \# Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net> \# -\# $Id: smartd.8,v 1.67 2003/02/27 23:19:16 ballen4705 Exp $ +\# $Id: smartd.8,v 1.68 2003/03/06 06:28:47 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 @@ -16,7 +16,7 @@ \# Research Center), Jack Baskin School of Engineering, University of \# California, Santa Cruz. http://ssrc.soe.ucsc.edu/ \# -.TH SMARTD 8 "$Date: 2003/02/27 23:19:16 $" "smartmontools-5.1" +.TH SMARTD 8 "$Date: 2003/03/06 06:28:47 $" "smartmontools-5.1" .SH NAME smartd \- S.M.A.R.T. Daemon .SH SYNOPSIS @@ -680,7 +680,7 @@ command-line option.] .TP .B \-u Report anytime that a Usage Attribute has changed its value -since the last check, N seconds ago. [Please see the +since the last check, 30 minutes ago. [Please see the .B smartctl \-A command-line option.] .TP @@ -688,7 +688,7 @@ command-line option.] Equivalent to turning on the two previous flags '\-p' and '\-u'. Tracks changes in .I all -device Attributes. [Please see the +device Attributes (both Prefailure and Usage). [Please see the .B smartctl \-A command-line option.] .TP @@ -697,8 +697,9 @@ Ignore device Attribute number .B ID when checking for failure of Usage Attributes. .B ID -must be a decimal integer in the range from 1 to 255. This Directive modifies -the behavior of the '\-f' Directive and has no effect without it. +must be a decimal integer in the range from 1 to 255. This Directive +modifies the behavior of the '\-f' Directive and has no effect without +it. This is useful, for example, if you have a very old disk and don't want to keep getting messages about the hours-on-lifetime Attribute (usually Attribute 9) @@ -711,13 +712,57 @@ Ignore device Attribute when tracking changes in the Attribute values. .B ID must be a decimal integer in the range from 1 to 255. This Directive modifies -the behavior of the '\-p', '\-u', and '\-t' Directives and has no effect -without one of them. +the behavior of the '\-p', '\-u', and '\-t' tracking Directives and has no effect +without one of them. This is useful, for example, if one of the device Attributes is the disk temperature (usually Attribute 194 or 231). It's annoying to get reports each time the temperature changes. This Directive may appear multiple times for a single device, if you want to ignore multiple Attributes. +.TP +.B \-r ID +When tracking, report the +.I Raw +value of Attribute +.B ID +along with its (normally reported) +.I Normalized +value. +.B ID +must be a decimal integer in the range from 1 to 255. This Directive modifies +the behavior of the '\-p', '\-u', and '\-t' tracking Directives and has no effect +without one of them. This Directive may be given multiple times. + +A common use of this Directive is to track the device Temperature +(often ID=194 or 231). + +.TP +.B \-R ID +When tracking, +report whenever the +.I Raw +value of Attribute +.B ID +changes. (Normally +.B smartd +only tracks/reports changes of the +.I Normalized +Attribute values.) +.B ID +must be a decimal integer in the range from 1 to 255. This Directive +modifies the behavior of the '\-p', '\-u', and '\-t' tracking Directives and +has no effect without one of them. This Directive may be given +multiple times. + +If this Directive is given, it automatically implies the '\-r' +Directive for the same Attribute, so that the Raw value of the +Attribute is reported. + +A common use of this Directive is to track the device Temperature +(often ID=194 or 231). It is also useful for understanding how +different types of system behavior affects the values of certain +Attributes. + .TP .B \-v N,OPTION Modifies the labeling for Attribute N, for disks which use @@ -860,6 +905,11 @@ then powers down the machine. Some example scripts are distributed with the smartmontools package, in /usr/share/doc/smartmontools-5.1/examplescripts/. +Please note that these scripts typically run as root, so any files +that they read/write should not be writable by ordinary users or +reside in directories like /tmp that are writable by ordinary users +and may expose your system to symlink attacks. + \# ENDINCLUDE \# DO NOT MODIFY THIS OR PREVIOUS/NEXT LINES. THIS DEFINES THE \# END OF THE INCLUDE SECTION FOR smartd.conf.5 @@ -977,4 +1027,4 @@ Please let us know if there is an on\-line source for this document. .SH CVS ID OF THIS PAGE: -$Id: smartd.8,v 1.67 2003/02/27 23:19:16 ballen4705 Exp $ +$Id: smartd.8,v 1.68 2003/03/06 06:28:47 ballen4705 Exp $ diff --git a/sm5/smartd.c b/sm5/smartd.c index bdca48d3b7d8d66c1d3b0b7ab293daf49f9c85b5..1a9cdd7f14186a01b90390284dcd375387b22564 100644 --- a/sm5/smartd.c +++ b/sm5/smartd.c @@ -50,7 +50,7 @@ // CVS ID strings extern const char *atacmds_c_cvsid, *ataprint_c_cvsid, *scsicmds_c_cvsid, *utility_c_cvsid; -const char *smartd_c_cvsid="$Id: smartd.c,v 1.110 2003/02/09 21:12:33 ballen4705 Exp $" +const char *smartd_c_cvsid="$Id: smartd.c,v 1.111 2003/03/06 06:28:47 ballen4705 Exp $" ATACMDS_H_CVSID ATAPRINT_H_CVSID EXTERN_H_CVSID SCSICMDS_H_CVSID SMARTD_H_CVSID UTILITY_H_CVSID; // global variable used for control of printing, passing arguments, etc. @@ -378,6 +378,8 @@ void Directives() { printout(LOG_INFO," -p Report changes in 'Prefailure' Attributes\n"); printout(LOG_INFO," -u Report changes in 'Usage' Attributes\n"); printout(LOG_INFO," -t Equivalent to -p and -u Directives\n"); + printout(LOG_INFO," -r ID Also report Raw values of Attribute ID with -p, -u or -t\n"); + printout(LOG_INFO," -R ID Track changes in Attribute ID Raw value with -p, -u or -t\n"); printout(LOG_INFO," -i ID Ignore Attribute ID for -f Directive\n"); printout(LOG_INFO," -I ID Ignore Attribute ID for -p, -u or -t Directive\n"); printout(LOG_INFO," -v N,ST Modifies labeling of Attribute N (see man page) \n"); @@ -700,22 +702,17 @@ int scsidevicescan(scsidevices_t *devices, cfgfile *cfg){ } // We compare old and new values of the n'th attribute. Note that n -// is NOT the attribute ID number.. If equal, return 0. The thre -// structure is used to verify that the attributes are valid ones. If -// the new value is lower than the old value, then we return both old -// and new values. new value=>lowest byte, old value=>next-to-lowest -// byte, id value=>next-to-next-to-lowest byte., and prefail flag x as -// bottom bit of highest byte. See below (lsb on right) - -// [00000000x][attribute ID][old value][new value] -int ataCompareSmartValues2(struct ata_smart_values *new, +// is NOT the attribute ID number.. If (Normalized & Raw) equal, +// then return 0, else nonzero. +int ataCompareSmartValues(changedattribute_t *delta, + struct ata_smart_values *new, struct ata_smart_values *old, struct ata_smart_thresholds *thresholds, int n, char *name){ struct ata_smart_attribute *now,*was; struct ata_smart_threshold_entry *thre; unsigned char oldval,newval; - int returnvalue; + int sameraw; // check that attribute number in range, and no null pointers if (n<0 || n>=NUMBER_ATA_SMART_ATTRIBUTES || !new || !old || !thresholds) @@ -738,22 +735,29 @@ int ataCompareSmartValues2(struct ata_smart_values *new, return 0; } - // if values have not changed, return + // new and old values of Normalized Attributes newval=now->current; oldval=was->current; - // if any values out of the allowed range, or the values haven't changed, return - if (!newval || !oldval || newval>0xfe || oldval>0xfe || oldval==newval) + // See if the RAW values are unchanged (ie, the same) + if (memcmp(now->raw, was->raw, 6)) + sameraw=0; + else + sameraw=1; + + // if any values out of the allowed range, or if the values haven't + // changed, return 0 + if (!newval || !oldval || newval>0xfe || oldval>0xfe || (oldval==newval && sameraw)) return 0; - // values have changed. Construct output - returnvalue=0; - returnvalue |= newval; - returnvalue |= oldval<<8; - returnvalue |= now->id<<16; - returnvalue |= (now->status.flag.prefailure)<<24; + // values have changed. Construct output and return + delta->newval=newval; + delta->oldval=oldval; + delta->id=now->id; + delta->prefail=now->status.flag.prefailure; + delta->sameraw=sameraw; - return returnvalue; + return 1; } // This looks to see if the corresponding bit of the 32 bytes is set. @@ -818,15 +822,17 @@ int ataCheckDevice(atadevices_t *drive){ // look for failed usage attributes, or track usage or prefail attributes for (i=0; i<NUMBER_ATA_SMART_ATTRIBUTES; i++){ int att; - + changedattribute_t delta; + + // This block looks for usage attributes that have failed. // Prefail attributes that have failed are returned with a // positive sign. No failure returns 0. Usage attributes<0. if (cfg->usagefailed && ((att=ataCheckAttribute(&curval, thresh, i))<0)){ - // are we tracking this attribute? + // are we ignoring failures of this attribute? att *= -1; - if (!isattoff(att, cfg->failatt, 0)){ + if (!isattoff(att, cfg->monitorattflags, 0)){ char attname[64], *loc=attname; // get attribute name & skip white space @@ -839,36 +845,46 @@ int ataCheckDevice(atadevices_t *drive){ } } - // This block tracks usage or prefailure attributes to see if they are changing - if ((cfg->usage || cfg->prefail) && ((att=ataCompareSmartValues2(&curval, drive->smartval, thresh, i, name)))){ - - // I should probably clean this up by defining a union to - // with one int=four unsigned chars to do this. - const int mask=0xff; - int newval =(att>>0) & mask; - int oldval =(att>>8) & mask; - int id =(att>>16) & mask; - int prefail=(att>>24) & mask; - - // for printing attribute name - char attname[64],*loc=attname; - + // This block tracks usage or prefailure attributes to see if + // they are changing. It also looks for changes in RAW values + // if this has been requested by user. + if ((cfg->usage || cfg->prefail) && ataCompareSmartValues(&delta, &curval, drive->smartval, thresh, i, name)){ + unsigned char id=delta.id; + + // if the only change is the raw value, and we're not + // tracking raw value, then continue loop over attributes + if (!delta.sameraw && delta.newval==delta.oldval && !isattoff(id, cfg->monitorattflags+96, 0)) + continue; + // are we tracking this attribute? - if (!isattoff(id, cfg->trackatt, 0)){ - + if (!isattoff(id, cfg->monitorattflags+32, 0)){ + char newrawstring[64], oldrawstring[64], attname[64], *loc=attname; + // get attribute name, skip spaces ataPrintSmartAttribName(loc, id, con->attributedefs); while (*loc && *loc==' ') loc++; + // has the user asked for us to print raw values? + if (isattoff(id, cfg->monitorattflags+64, 0)) { + // get raw values (as a string) and add to printout + char rawstring[64]; + ataPrintSmartAttribRawValue(rawstring, curval.vendor_attributes+i, con->attributedefs); + sprintf(newrawstring, " [Raw %s]", rawstring); + ataPrintSmartAttribRawValue(rawstring, drive->smartval->vendor_attributes+i, con->attributedefs); + sprintf(oldrawstring, " [Raw %s]", rawstring); + } + else + newrawstring[0]=oldrawstring[0]='\0'; + // prefailure attribute - if (cfg->prefail && prefail) - printout(LOG_INFO, "Device: %s, SMART Prefailure Attribute: %s changed from %d to %d\n", - name, loc, (int)oldval, (int)newval); + if (cfg->prefail && delta.prefail) + printout(LOG_INFO, "Device: %s, SMART Prefailure Attribute: %s changed from %d%s to %d%s\n", + name, loc, delta.oldval, oldrawstring, delta.newval, newrawstring); // usage attribute - if (cfg->usage && !prefail) - printout(LOG_INFO, "Device: %s, SMART Usage Attribute: %s changed from %d to %d\n", - name, loc, (int)oldval, (int)newval); + if (cfg->usage && !delta.prefail) + printout(LOG_INFO, "Device: %s, SMART Usage Attribute: %s changed from %d%s to %d%s\n", + name, loc, delta.oldval, oldrawstring, delta.newval, newrawstring); } } // endof block tracking usage or prefailure } // end of loop over attributes @@ -1231,12 +1247,23 @@ int parsetoken(char *token,cfgfile *cfg){ case 'i': // ignore failure of usage attribute val=inttoken(arg=strtok(NULL,delim), name, token, lineno, CONFIGFILE, 1, 255); - isattoff(val,cfg->failatt,1); + isattoff(val,cfg->monitorattflags,1); break; case 'I': // ignore attribute for tracking purposes val=inttoken(arg=strtok(NULL,delim), name, token, lineno, CONFIGFILE, 1, 255); - isattoff(val,cfg->trackatt,1); + isattoff(val,cfg->monitorattflags+32,1); + break; + case 'r': + // print raw value when tracking + val=inttoken(arg=strtok(NULL,delim), name, token, lineno, CONFIGFILE, 1, 255); + isattoff(val,cfg->monitorattflags+64,1); + break; + case 'R': + // track changes in raw value (forces printing of raw value) + val=inttoken(arg=strtok(NULL,delim), name, token, lineno, CONFIGFILE, 1, 255); + isattoff(val,cfg->monitorattflags+64,1); + isattoff(val,cfg->monitorattflags+96,1); break; case 'm': // send email to address that follows @@ -1331,13 +1358,12 @@ int parseconfigline(int entry, int lineno,char *line){ // bit per possible attribute ID. See isattoff() cfg->name=strdup(name); if (!devscan){ - cfg->failatt=(unsigned char *)calloc(32,1); - cfg->trackatt=(unsigned char *)calloc(32,1); + cfg->monitorattflags=(unsigned char *)calloc(NMONITOR*32,1); cfg->attributedefs=(unsigned char *)calloc(256,1); } // check that all memory allocations were sucessful - if (!cfg->name || (!devscan && (!cfg->failatt || !cfg->trackatt || !cfg->attributedefs))) { + if (!cfg->name || (!devscan && (!cfg->monitorattflags || !cfg->attributedefs))) { printout(LOG_INFO,"No memory to store file: %s line %d, %s\n", CONFIGFILE, lineno, strerror(errno)); exit(1); } @@ -1693,10 +1719,9 @@ int makeconfigentries(int num, char *name, int isata, int start, int scandirecti // put in the device name cfg->name=strdup(name); - cfg->failatt=(unsigned char *)calloc(32,1); - cfg->trackatt=(unsigned char *)calloc(32,1); + cfg->monitorattflags=(unsigned char *)calloc(NMONITOR*32,1); cfg->attributedefs=(unsigned char *)calloc(256,1); - if (!cfg->name || !cfg->failatt || !cfg->trackatt || !cfg->attributedefs) { + if (!cfg->name || !cfg->monitorattflags || !cfg->attributedefs) { printout(LOG_INFO,"No memory for %d'th device after %s, %s\n", i, name, strerror(errno)); exit(1); } diff --git a/sm5/smartd.conf b/sm5/smartd.conf index 1cfac908e02c8019e56936386e5bde284e5ee2d0..2790af6d5a74b99c11598ea71db35032ae53238d 100644 --- a/sm5/smartd.conf +++ b/sm5/smartd.conf @@ -44,9 +44,11 @@ DEVICESCAN # -f Monitor for failure of any 'Usage' Attributes # -m ADD Send warning email to ADD for -H, -l error, -l selftest, and -f # -M TYPE Modify email warning behavior (see man page) -# -p Report changes in 'Prefailure' Attributes -# -u Report changes in 'Usage' Attributes +# -p Report changes in 'Prefailure' Normalized Attributes +# -u Report changes in 'Usage' Normalized Attributes # -t Equivalent to -p and -u Directives +# -r ID Also report Raw values of Attribute ID with -p, -u or -t +# -R ID Track changes in Attribute ID Raw value with -p, -u or -t # -i ID Ignore Attribute ID for -f Directive # -I ID Ignore Attribute ID for -p, -u or -t Directive # -v N,ST Modifies labeling of Attribute N (see man page) diff --git a/sm5/smartd.conf.5 b/sm5/smartd.conf.5 index 56cabcbf0c144593de33df62b3389eb86647c4bc..7012bff9835f4c752d20e8d6738d2337fe500f79 100644 --- a/sm5/smartd.conf.5 +++ b/sm5/smartd.conf.5 @@ -1,6 +1,6 @@ \# Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net> \# -\# $Id: smartd.conf.5,v 1.31 2003/02/24 15:51:39 ballen4705 Exp $ +\# $Id: smartd.conf.5,v 1.32 2003/03/06 06:28:47 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 @@ -16,7 +16,7 @@ \# Research Center), Jack Baskin School of Engineering, University of \# California, Santa Cruz. http://ssrc.soe.ucsc.edu/ \# -.TH SMARTD.CONF 5 "$Date: 2003/02/24 15:51:39 $" "smartmontools-5.1" +.TH SMARTD.CONF 5 "$Date: 2003/03/06 06:28:47 $" "smartmontools-5.1" .SH NAME smartd.conf \- S.M.A.R.T. Monitoring Daemon Configuration File @@ -478,7 +478,7 @@ command-line option.] .TP .B \-u Report anytime that a Usage Attribute has changed its value -since the last check, N seconds ago. [Please see the +since the last check, 30 minutes ago. [Please see the .B smartctl \-A command-line option.] .TP @@ -486,7 +486,7 @@ command-line option.] Equivalent to turning on the two previous flags '\-p' and '\-u'. Tracks changes in .I all -device Attributes. [Please see the +device Attributes (both Prefailure and Usage). [Please see the .B smartctl \-A command-line option.] .TP @@ -495,8 +495,9 @@ Ignore device Attribute number .B ID when checking for failure of Usage Attributes. .B ID -must be a decimal integer in the range from 1 to 255. This Directive modifies -the behavior of the '\-f' Directive and has no effect without it. +must be a decimal integer in the range from 1 to 255. This Directive +modifies the behavior of the '\-f' Directive and has no effect without +it. This is useful, for example, if you have a very old disk and don't want to keep getting messages about the hours-on-lifetime Attribute (usually Attribute 9) @@ -509,13 +510,57 @@ Ignore device Attribute when tracking changes in the Attribute values. .B ID must be a decimal integer in the range from 1 to 255. This Directive modifies -the behavior of the '\-p', '\-u', and '\-t' Directives and has no effect -without one of them. +the behavior of the '\-p', '\-u', and '\-t' tracking Directives and has no effect +without one of them. This is useful, for example, if one of the device Attributes is the disk temperature (usually Attribute 194 or 231). It's annoying to get reports each time the temperature changes. This Directive may appear multiple times for a single device, if you want to ignore multiple Attributes. +.TP +.B \-r ID +When tracking, report the +.I Raw +value of Attribute +.B ID +along with its (normally reported) +.I Normalized +value. +.B ID +must be a decimal integer in the range from 1 to 255. This Directive modifies +the behavior of the '\-p', '\-u', and '\-t' tracking Directives and has no effect +without one of them. This Directive may be given multiple times. + +A common use of this Directive is to track the device Temperature +(often ID=194 or 231). + +.TP +.B \-R ID +When tracking, +report whenever the +.I Raw +value of Attribute +.B ID +changes. (Normally +.B smartd +only tracks/reports changes of the +.I Normalized +Attribute values.) +.B ID +must be a decimal integer in the range from 1 to 255. This Directive +modifies the behavior of the '\-p', '\-u', and '\-t' tracking Directives and +has no effect without one of them. This Directive may be given +multiple times. + +If this Directive is given, it automatically implies the '\-r' +Directive for the same Attribute, so that the Raw value of the +Attribute is reported. + +A common use of this Directive is to track the device Temperature +(often ID=194 or 231). It is also useful for understanding how +different types of system behavior affects the values of certain +Attributes. + .TP .B \-v N,OPTION Modifies the labeling for Attribute N, for disks which use @@ -658,6 +703,11 @@ then powers down the machine. Some example scripts are distributed with the smartmontools package, in /usr/share/doc/smartmontools-5.1/examplescripts/. +Please note that these scripts typically run as root, so any files +that they read/write should not be writable by ordinary users or +reside in directories like /tmp that are writable by ordinary users +and may expose your system to symlink attacks. + \# ENDINCLUDE \# DO NOT MODIFY THIS OR PREVIOUS/NEXT LINES. THIS DEFINES THE \# END OF THE INCLUDED SECTION FROM smartd.8 @@ -701,4 +751,4 @@ SEE ALSO: .SH CVS ID OF THIS PAGE: -$Id: smartd.conf.5,v 1.31 2003/02/24 15:51:39 ballen4705 Exp $ +$Id: smartd.conf.5,v 1.32 2003/03/06 06:28:47 ballen4705 Exp $ diff --git a/sm5/smartd.cpp b/sm5/smartd.cpp index edf101f12f160596bfd0888e25c08dbef7b404fb..3ba93a940db9f68ce1a18b40fae7be363587d780 100644 --- a/sm5/smartd.cpp +++ b/sm5/smartd.cpp @@ -50,7 +50,7 @@ // CVS ID strings extern const char *atacmds_c_cvsid, *ataprint_c_cvsid, *scsicmds_c_cvsid, *utility_c_cvsid; -const char *smartd_c_cvsid="$Id: smartd.cpp,v 1.110 2003/02/09 21:12:33 ballen4705 Exp $" +const char *smartd_c_cvsid="$Id: smartd.cpp,v 1.111 2003/03/06 06:28:47 ballen4705 Exp $" ATACMDS_H_CVSID ATAPRINT_H_CVSID EXTERN_H_CVSID SCSICMDS_H_CVSID SMARTD_H_CVSID UTILITY_H_CVSID; // global variable used for control of printing, passing arguments, etc. @@ -378,6 +378,8 @@ void Directives() { printout(LOG_INFO," -p Report changes in 'Prefailure' Attributes\n"); printout(LOG_INFO," -u Report changes in 'Usage' Attributes\n"); printout(LOG_INFO," -t Equivalent to -p and -u Directives\n"); + printout(LOG_INFO," -r ID Also report Raw values of Attribute ID with -p, -u or -t\n"); + printout(LOG_INFO," -R ID Track changes in Attribute ID Raw value with -p, -u or -t\n"); printout(LOG_INFO," -i ID Ignore Attribute ID for -f Directive\n"); printout(LOG_INFO," -I ID Ignore Attribute ID for -p, -u or -t Directive\n"); printout(LOG_INFO," -v N,ST Modifies labeling of Attribute N (see man page) \n"); @@ -700,22 +702,17 @@ int scsidevicescan(scsidevices_t *devices, cfgfile *cfg){ } // We compare old and new values of the n'th attribute. Note that n -// is NOT the attribute ID number.. If equal, return 0. The thre -// structure is used to verify that the attributes are valid ones. If -// the new value is lower than the old value, then we return both old -// and new values. new value=>lowest byte, old value=>next-to-lowest -// byte, id value=>next-to-next-to-lowest byte., and prefail flag x as -// bottom bit of highest byte. See below (lsb on right) - -// [00000000x][attribute ID][old value][new value] -int ataCompareSmartValues2(struct ata_smart_values *new, +// is NOT the attribute ID number.. If (Normalized & Raw) equal, +// then return 0, else nonzero. +int ataCompareSmartValues(changedattribute_t *delta, + struct ata_smart_values *new, struct ata_smart_values *old, struct ata_smart_thresholds *thresholds, int n, char *name){ struct ata_smart_attribute *now,*was; struct ata_smart_threshold_entry *thre; unsigned char oldval,newval; - int returnvalue; + int sameraw; // check that attribute number in range, and no null pointers if (n<0 || n>=NUMBER_ATA_SMART_ATTRIBUTES || !new || !old || !thresholds) @@ -738,22 +735,29 @@ int ataCompareSmartValues2(struct ata_smart_values *new, return 0; } - // if values have not changed, return + // new and old values of Normalized Attributes newval=now->current; oldval=was->current; - // if any values out of the allowed range, or the values haven't changed, return - if (!newval || !oldval || newval>0xfe || oldval>0xfe || oldval==newval) + // See if the RAW values are unchanged (ie, the same) + if (memcmp(now->raw, was->raw, 6)) + sameraw=0; + else + sameraw=1; + + // if any values out of the allowed range, or if the values haven't + // changed, return 0 + if (!newval || !oldval || newval>0xfe || oldval>0xfe || (oldval==newval && sameraw)) return 0; - // values have changed. Construct output - returnvalue=0; - returnvalue |= newval; - returnvalue |= oldval<<8; - returnvalue |= now->id<<16; - returnvalue |= (now->status.flag.prefailure)<<24; + // values have changed. Construct output and return + delta->newval=newval; + delta->oldval=oldval; + delta->id=now->id; + delta->prefail=now->status.flag.prefailure; + delta->sameraw=sameraw; - return returnvalue; + return 1; } // This looks to see if the corresponding bit of the 32 bytes is set. @@ -818,15 +822,17 @@ int ataCheckDevice(atadevices_t *drive){ // look for failed usage attributes, or track usage or prefail attributes for (i=0; i<NUMBER_ATA_SMART_ATTRIBUTES; i++){ int att; - + changedattribute_t delta; + + // This block looks for usage attributes that have failed. // Prefail attributes that have failed are returned with a // positive sign. No failure returns 0. Usage attributes<0. if (cfg->usagefailed && ((att=ataCheckAttribute(&curval, thresh, i))<0)){ - // are we tracking this attribute? + // are we ignoring failures of this attribute? att *= -1; - if (!isattoff(att, cfg->failatt, 0)){ + if (!isattoff(att, cfg->monitorattflags, 0)){ char attname[64], *loc=attname; // get attribute name & skip white space @@ -839,36 +845,46 @@ int ataCheckDevice(atadevices_t *drive){ } } - // This block tracks usage or prefailure attributes to see if they are changing - if ((cfg->usage || cfg->prefail) && ((att=ataCompareSmartValues2(&curval, drive->smartval, thresh, i, name)))){ - - // I should probably clean this up by defining a union to - // with one int=four unsigned chars to do this. - const int mask=0xff; - int newval =(att>>0) & mask; - int oldval =(att>>8) & mask; - int id =(att>>16) & mask; - int prefail=(att>>24) & mask; - - // for printing attribute name - char attname[64],*loc=attname; - + // This block tracks usage or prefailure attributes to see if + // they are changing. It also looks for changes in RAW values + // if this has been requested by user. + if ((cfg->usage || cfg->prefail) && ataCompareSmartValues(&delta, &curval, drive->smartval, thresh, i, name)){ + unsigned char id=delta.id; + + // if the only change is the raw value, and we're not + // tracking raw value, then continue loop over attributes + if (!delta.sameraw && delta.newval==delta.oldval && !isattoff(id, cfg->monitorattflags+96, 0)) + continue; + // are we tracking this attribute? - if (!isattoff(id, cfg->trackatt, 0)){ - + if (!isattoff(id, cfg->monitorattflags+32, 0)){ + char newrawstring[64], oldrawstring[64], attname[64], *loc=attname; + // get attribute name, skip spaces ataPrintSmartAttribName(loc, id, con->attributedefs); while (*loc && *loc==' ') loc++; + // has the user asked for us to print raw values? + if (isattoff(id, cfg->monitorattflags+64, 0)) { + // get raw values (as a string) and add to printout + char rawstring[64]; + ataPrintSmartAttribRawValue(rawstring, curval.vendor_attributes+i, con->attributedefs); + sprintf(newrawstring, " [Raw %s]", rawstring); + ataPrintSmartAttribRawValue(rawstring, drive->smartval->vendor_attributes+i, con->attributedefs); + sprintf(oldrawstring, " [Raw %s]", rawstring); + } + else + newrawstring[0]=oldrawstring[0]='\0'; + // prefailure attribute - if (cfg->prefail && prefail) - printout(LOG_INFO, "Device: %s, SMART Prefailure Attribute: %s changed from %d to %d\n", - name, loc, (int)oldval, (int)newval); + if (cfg->prefail && delta.prefail) + printout(LOG_INFO, "Device: %s, SMART Prefailure Attribute: %s changed from %d%s to %d%s\n", + name, loc, delta.oldval, oldrawstring, delta.newval, newrawstring); // usage attribute - if (cfg->usage && !prefail) - printout(LOG_INFO, "Device: %s, SMART Usage Attribute: %s changed from %d to %d\n", - name, loc, (int)oldval, (int)newval); + if (cfg->usage && !delta.prefail) + printout(LOG_INFO, "Device: %s, SMART Usage Attribute: %s changed from %d%s to %d%s\n", + name, loc, delta.oldval, oldrawstring, delta.newval, newrawstring); } } // endof block tracking usage or prefailure } // end of loop over attributes @@ -1231,12 +1247,23 @@ int parsetoken(char *token,cfgfile *cfg){ case 'i': // ignore failure of usage attribute val=inttoken(arg=strtok(NULL,delim), name, token, lineno, CONFIGFILE, 1, 255); - isattoff(val,cfg->failatt,1); + isattoff(val,cfg->monitorattflags,1); break; case 'I': // ignore attribute for tracking purposes val=inttoken(arg=strtok(NULL,delim), name, token, lineno, CONFIGFILE, 1, 255); - isattoff(val,cfg->trackatt,1); + isattoff(val,cfg->monitorattflags+32,1); + break; + case 'r': + // print raw value when tracking + val=inttoken(arg=strtok(NULL,delim), name, token, lineno, CONFIGFILE, 1, 255); + isattoff(val,cfg->monitorattflags+64,1); + break; + case 'R': + // track changes in raw value (forces printing of raw value) + val=inttoken(arg=strtok(NULL,delim), name, token, lineno, CONFIGFILE, 1, 255); + isattoff(val,cfg->monitorattflags+64,1); + isattoff(val,cfg->monitorattflags+96,1); break; case 'm': // send email to address that follows @@ -1331,13 +1358,12 @@ int parseconfigline(int entry, int lineno,char *line){ // bit per possible attribute ID. See isattoff() cfg->name=strdup(name); if (!devscan){ - cfg->failatt=(unsigned char *)calloc(32,1); - cfg->trackatt=(unsigned char *)calloc(32,1); + cfg->monitorattflags=(unsigned char *)calloc(NMONITOR*32,1); cfg->attributedefs=(unsigned char *)calloc(256,1); } // check that all memory allocations were sucessful - if (!cfg->name || (!devscan && (!cfg->failatt || !cfg->trackatt || !cfg->attributedefs))) { + if (!cfg->name || (!devscan && (!cfg->monitorattflags || !cfg->attributedefs))) { printout(LOG_INFO,"No memory to store file: %s line %d, %s\n", CONFIGFILE, lineno, strerror(errno)); exit(1); } @@ -1693,10 +1719,9 @@ int makeconfigentries(int num, char *name, int isata, int start, int scandirecti // put in the device name cfg->name=strdup(name); - cfg->failatt=(unsigned char *)calloc(32,1); - cfg->trackatt=(unsigned char *)calloc(32,1); + cfg->monitorattflags=(unsigned char *)calloc(NMONITOR*32,1); cfg->attributedefs=(unsigned char *)calloc(256,1); - if (!cfg->name || !cfg->failatt || !cfg->trackatt || !cfg->attributedefs) { + if (!cfg->name || !cfg->monitorattflags || !cfg->attributedefs) { printout(LOG_INFO,"No memory for %d'th device after %s, %s\n", i, name, strerror(errno)); exit(1); } diff --git a/sm5/smartd.h b/sm5/smartd.h index 358e3f65bb9fdcaeca961741e8b08f1e4ff6b822..06190d33187cc039e2b0902a889d926c89c9ddef 100644 --- a/sm5/smartd.h +++ b/sm5/smartd.h @@ -23,7 +23,7 @@ */ #ifndef SMARTD_H_CVSID -#define SMARTD_H_CVSID "$Id: smartd.h,v 1.28 2003/01/31 03:45:25 ballen4705 Exp $\n" +#define SMARTD_H_CVSID "$Id: smartd.h,v 1.29 2003/03/06 06:28:47 ballen4705 Exp $\n" #endif // Configuration file @@ -54,6 +54,10 @@ #define TRUE 0x01 #define FALSE 0x00 +// Number of monitoring flags per Attribute. See monitorattflags +// below. +#define NMONITOR 4 + // If user has requested email warning messages, then this structure // stores the information about them. @@ -108,12 +112,14 @@ typedef struct configfile_s { // atadevices_t structure. unsigned char selflogcount; int ataerrorcount; - // following two items point to 32 bytes, in the form of + // following NMONITOR items each point to 32 bytes, in the form of // 32x8=256 single bit flags // valid attribute numbers are from 1 <= x <= 255 - // valid attribute values are from 1 <= x <= 254 - unsigned char *failatt; - unsigned char *trackatt; + // monitorattflags+0 set means ignore failure if it's a usage attribute + // monitorattflats+32 set means don't track attribute + // monitorattflags+64 set means print raw value when tracking + // monitorattflags+96 set means track changes in raw value + unsigned char *monitorattflags; // See the end of extern.h for a definition of the array of 256 // bytes that this points to. unsigned char *attributedefs; @@ -139,6 +145,14 @@ typedef struct scsidevices_s { } scsidevices_t; +typedef struct changedattribute_s { + unsigned char newval; + unsigned char oldval; + unsigned char id; + unsigned char prefail; + unsigned char sameraw; +} changedattribute_t; + // Declare our own printing functions... void printout(int priority,char *fmt, ...) __attribute__ ((format(printf, 2, 3))); void printandmail(cfgfile *cfg, int which, int priority, char *fmt, ...) __attribute__ ((format(printf, 4, 5))); diff --git a/sm5/smartmontools.spec b/sm5/smartmontools.spec index a7eb6b2a0c255ab360fb7cf67903b70f144bbadb..42dd0417c38e13edba500346c3893db8152d031b 100644 --- a/sm5/smartmontools.spec +++ b/sm5/smartmontools.spec @@ -1,4 +1,4 @@ -Release: 7 +Release: 8 Summary: SMARTmontools - for monitoring S.M.A.R.T. disks and devices Summary(cs): SMARTmontools - pro monitorov�n� S.M.A.R.T. disk� a za��zen� Summary(de): SMARTmontools - zur �berwachung von S.M.A.R.T.-Platten und-Ger�ten @@ -30,7 +30,7 @@ Packager: Bruce Allen <smartmontools-support@lists.sourceforge.net> # http://ftp1.sourceforge.net/smartmontools/smartmontools-%{version}-%{release}.tar.gz # CVS ID of this file is: -# $Id: smartmontools.spec,v 1.90 2003/02/18 21:23:22 ballen4705 Exp $ +# $Id: smartmontools.spec,v 1.91 2003/03/06 06:28:47 ballen4705 Exp $ # Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net> # Home page: http://smartmontools.sourceforge.net/