From 64d71c146a0da91f7b708ac5637aa0b20cbf06c2 Mon Sep 17 00:00:00 2001 From: ballen4705 <ballen4705@4ea69e1a-61f1-4043-bf83-b5c94c648137> Date: Wed, 13 Aug 2003 12:33:23 +0000 Subject: [PATCH] Additional work on dynamic memory allocation/deallocation. This should have no effect on smartctl, but clears that way for smartd to dynamically add and remove entries. It should also now be easier to modify smartd to re-read its config file on HUP (which is easy) without leaking memory (which is harder). The philosophy is that memory for data structures in smartd is now allocated only on demand, the first time it is needed. git-svn-id: https://smartmontools.svn.sourceforge.net/svnroot/smartmontools/trunk@882 4ea69e1a-61f1-4043-bf83-b5c94c648137 --- sm5/CHANGELOG | 11 ++++- sm5/atacmdnames.c | 12 ++--- sm5/atacmdnames.cpp | 12 ++--- sm5/atacmds.c | 56 ++++++++++++++++------- sm5/atacmds.cpp | 56 ++++++++++++++++------- sm5/atacmds.h | 13 ++++-- sm5/ataprint.c | 19 +++++--- sm5/ataprint.cpp | 19 +++++--- sm5/knowndrives.c | 53 ++++++++++++---------- sm5/knowndrives.cpp | 53 ++++++++++++---------- sm5/knowndrives.h | 4 +- sm5/smartctl.c | 53 ++++++++++++---------- sm5/smartctl.cpp | 53 ++++++++++++---------- sm5/smartd.8 | 20 ++++----- sm5/smartd.c | 107 ++++++++++++++++++++++++++------------------ sm5/smartd.cpp | 107 ++++++++++++++++++++++++++------------------ sm5/smartd.h | 10 +++-- 17 files changed, 400 insertions(+), 258 deletions(-) diff --git a/sm5/CHANGELOG b/sm5/CHANGELOG index 103a98292..c3fcca188 100644 --- a/sm5/CHANGELOG +++ b/sm5/CHANGELOG @@ -1,6 +1,6 @@ CHANGELOG for smartmontools -$Id: CHANGELOG,v 1.174 2003/08/11 14:21:51 ballen4705 Exp $ +$Id: CHANGELOG,v 1.175 2003/08/13 12:33:22 ballen4705 Exp $ Copyright (C) 2002-3 Bruce Allen <smartmontools-support@lists.sourceforge.net> @@ -38,6 +38,15 @@ CURRENT DEVELOPMENT VERSION (see VERSION file in this directory): <ADDITIONS TO THE CHANGE LOG SHOULD BE ADDED HERE, PLEASE> + [BA] Additional work on dynamic memory allocation/deallocation. + This should have no effect on smartctl, but clears that way + for smartd to dynamically add and remove entries. It should + also now be easier to modify smartd to re-read its config + file on HUP (which is easy) without leaking memory (which is + harder). The philosophy is that memory for data structures in + smartd is now allocated only on demand, the first time it + is needed. + [BA] smartd: finished cleanup. Now use create/rm functions for cfgentries and dynamic memory allocation almost everywhere. Philosophy: aggresively try and provoke SEGV to help find diff --git a/sm5/atacmdnames.c b/sm5/atacmdnames.c index e4b9a1a80..5242c0229 100644 --- a/sm5/atacmdnames.c +++ b/sm5/atacmdnames.c @@ -24,7 +24,9 @@ #include <stdlib.h> #include <stdio.h> -const char *atacmdnames_c_cvsid="$Id: atacmdnames.c,v 1.8 2003/07/23 21:35:12 pjwilliams Exp $" ATACMDNAMES_H_CVSID; +#define COMMAND_TABLE_SIZE 256 + +const char *atacmdnames_c_cvsid="$Id: atacmdnames.c,v 1.9 2003/08/13 12:33:22 ballen4705 Exp $" ATACMDNAMES_H_CVSID; const char cmd_reserved[] = "[RESERVED]"; const char cmd_vendor_specific[] = "[VENDOR SPECIFIC]"; @@ -34,7 +36,7 @@ const char cmd_reserved_mcpt[] = "[RESERVED FOR MEDIA CARD PASS THROUGH]"; const char cmd_recalibrate_ret4[]= "RECALIBRATE [RET-4]"; const char cmd_seek_ret4[] = "SEEK [RET-4]"; -const char *command_table[256] = { +const char *command_table[COMMAND_TABLE_SIZE] = { /*-------------------------------------------------- 00h-0Fh -----*/ "NOP", cmd_reserved, @@ -322,11 +324,11 @@ const char *look_up_ata_command(unsigned char c_code, unsigned char f_reg) { // check that command table not messed up. The compiler will issue // warnings if there are too many array elements, but won't issue // warnings if there are not enough of them. - if (sizeof(command_table) != sizeof(char *)*256){ + if (sizeof(command_table) != sizeof(char *)*COMMAND_TABLE_SIZE){ fprintf(stderr, "Problem in atacmdnames.c. Command Table command_table[] does\n" - "not have 256 entries! It has %d entries. Please fix it.\n", - (int)(sizeof(command_table)/sizeof(char *))); + "not have %d entries! It has %d entries. Please fix it.\n", + COMMAND_TABLE_SIZE, (int)(sizeof(command_table)/sizeof(char *))); abort(); } diff --git a/sm5/atacmdnames.cpp b/sm5/atacmdnames.cpp index 594f924e0..8291fc3dc 100644 --- a/sm5/atacmdnames.cpp +++ b/sm5/atacmdnames.cpp @@ -24,7 +24,9 @@ #include <stdlib.h> #include <stdio.h> -const char *atacmdnames_c_cvsid="$Id: atacmdnames.cpp,v 1.8 2003/07/23 21:35:12 pjwilliams Exp $" ATACMDNAMES_H_CVSID; +#define COMMAND_TABLE_SIZE 256 + +const char *atacmdnames_c_cvsid="$Id: atacmdnames.cpp,v 1.9 2003/08/13 12:33:22 ballen4705 Exp $" ATACMDNAMES_H_CVSID; const char cmd_reserved[] = "[RESERVED]"; const char cmd_vendor_specific[] = "[VENDOR SPECIFIC]"; @@ -34,7 +36,7 @@ const char cmd_reserved_mcpt[] = "[RESERVED FOR MEDIA CARD PASS THROUGH]"; const char cmd_recalibrate_ret4[]= "RECALIBRATE [RET-4]"; const char cmd_seek_ret4[] = "SEEK [RET-4]"; -const char *command_table[256] = { +const char *command_table[COMMAND_TABLE_SIZE] = { /*-------------------------------------------------- 00h-0Fh -----*/ "NOP", cmd_reserved, @@ -322,11 +324,11 @@ const char *look_up_ata_command(unsigned char c_code, unsigned char f_reg) { // check that command table not messed up. The compiler will issue // warnings if there are too many array elements, but won't issue // warnings if there are not enough of them. - if (sizeof(command_table) != sizeof(char *)*256){ + if (sizeof(command_table) != sizeof(char *)*COMMAND_TABLE_SIZE){ fprintf(stderr, "Problem in atacmdnames.c. Command Table command_table[] does\n" - "not have 256 entries! It has %d entries. Please fix it.\n", - (int)(sizeof(command_table)/sizeof(char *))); + "not have %d entries! It has %d entries. Please fix it.\n", + COMMAND_TABLE_SIZE, (int)(sizeof(command_table)/sizeof(char *))); abort(); } diff --git a/sm5/atacmds.c b/sm5/atacmds.c index 9649e5569..2630215ea 100644 --- a/sm5/atacmds.c +++ b/sm5/atacmds.c @@ -33,7 +33,7 @@ #include "extern.h" #include "utility.h" -const char *atacmds_c_cvsid="$Id: atacmds.c,v 1.114 2003/08/05 16:27:43 ballen4705 Exp $" ATACMDS_H_CVSID ESCALADE_H_CVSID EXTERN_H_CVSID UTILITY_H_CVSID; +const char *atacmds_c_cvsid="$Id: atacmds.c,v 1.115 2003/08/13 12:33:22 ballen4705 Exp $" ATACMDS_H_CVSID ESCALADE_H_CVSID EXTERN_H_CVSID UTILITY_H_CVSID; // for passing global control variables extern smartmonctrl *con; @@ -172,9 +172,18 @@ const char *vendorattributeargs[] = { // This is a utility function for parsing pairs like "9,minutes" or // "220,temp", and putting the correct flag into the attributedefs // array. Returns 1 if problem, 0 if pair has been recongized. -int parse_attribute_def(char *pair, unsigned char *defs){ +int parse_attribute_def(char *pair, unsigned char **defsptr){ int i,j; char temp[32]; + unsigned char *defs; + + // If array does not exist, allocate it + if (!*defsptr && !(*defsptr=(unsigned char *)calloc(MAX_ATTRIBUTE_NUM, 1))){ + pout("Out of memory in parse_attribute_def\n"); + exit(1); + } + + defs=*defsptr; // look along list and see if we find the pair for (i=0; vendorattributeargs[i] && strcmp(pair, vendorattributeargs[i]); i++); @@ -198,17 +207,17 @@ int parse_attribute_def(char *pair, unsigned char *defs){ return 0; case 4: // print all attributes in raw 8-bit form - for (j=0; j<256; j++) + for (j=0; j<MAX_ATTRIBUTE_NUM; j++) defs[j]=253; return 0; case 5: // print all attributes in raw 16-bit form - for (j=0; j<256; j++) + for (j=0; j<MAX_ATTRIBUTE_NUM; j++) defs[j]=254; return 0; case 6: // print all attributes in raw 48-bit form - for (j=0; j<256; j++) + for (j=0; j<MAX_ATTRIBUTE_NUM; j++) defs[j]=255; return 0; case 7: @@ -663,7 +672,7 @@ int smartcommandhandler(int device, smart_command_set command, int select, char pout("\n"); } - if (getsdata && data==NULL){ + if (getsdata && !data){ pout("REPORT-IOCTL: Unable to execute command %s : data destination address is NULL\n", commandstrings[command]); return -1; } @@ -1378,6 +1387,7 @@ long long ataPrintSmartAttribRawValue(char *out, long long rawvalue; unsigned word[3]; int j; + unsigned char select; // convert the six individual bytes to a long long (8 byte) integer. // This is the value that we'll eventually return. @@ -1400,8 +1410,14 @@ long long ataPrintSmartAttribRawValue(char *out, word[j] |= attribute->raw[2*j]; } + // if no data array, Attributes have default interpretations + if (defs) + select=defs[attribute->id]; + else + select=0; + // Print six one-byte quantities. - if (defs[attribute->id]==253){ + if (select==253){ for (j=0; j<5; j++) out+=sprintf(out, "%d ", attribute->raw[5-j]); out+=sprintf(out, "%d ", attribute->raw[0]); @@ -1409,13 +1425,13 @@ long long ataPrintSmartAttribRawValue(char *out, } // Print three two-byte quantities - if (defs[attribute->id]==254){ + if (select==254){ out+=sprintf(out, "%d %d %d", word[2], word[1], word[0]); return rawvalue; } // Print one six-byte quantity - if (defs[attribute->id]==255){ + if (select==255){ out+=sprintf(out, "%llu", rawvalue); return rawvalue; } @@ -1432,20 +1448,20 @@ long long ataPrintSmartAttribRawValue(char *out, break; // Power on time case 9: - if (defs[9]==1){ + if (select==1){ // minutes long long tmp1=rawvalue/60; long long tmp2=rawvalue%60; out+=sprintf(out, "%lluh+%02llum", tmp1, tmp2); } - else if (defs[9]==3){ + else if (select==3){ // seconds long long hours=rawvalue/3600; long long minutes=(rawvalue-3600*hours)/60; long long seconds=rawvalue%60; out+=sprintf(out, "%lluh+%02llum+%02llus", hours, minutes, seconds); } - else if (defs[9]==4){ + else if (select==4){ // 30-second counter long long tmp1=rawvalue/120; long long tmp2=(rawvalue-120*tmp1)/2; @@ -1457,7 +1473,7 @@ long long ataPrintSmartAttribRawValue(char *out, break; // Load unload cycles case 193: - if (defs[193]==1){ + if (select==1){ // loadunload long load =attribute->raw[0] + (attribute->raw[1]<<8) + (attribute->raw[2]<<16); long unload=attribute->raw[3] + (attribute->raw[4]<<8) + (attribute->raw[5]<<16); @@ -1469,13 +1485,13 @@ long long ataPrintSmartAttribRawValue(char *out, break; // Temperature case 194: - if (defs[194]==1){ + if (select==1){ // ten times temperature in Celsius int deg=word[0]/10; int tenths=word[0]%10; out+=sprintf(out, "%d.%d", deg, tenths); } - else if (defs[194]==2) + else if (select==2) // unknown attribute out+=sprintf(out, "%llu", rawvalue); else { @@ -1498,8 +1514,16 @@ long long ataPrintSmartAttribRawValue(char *out, // manufacturers use different attribute IDs for an attribute with the // same name. The variable val should contain a non-zero value if a particular // attributes has a non-default interpretation. -void ataPrintSmartAttribName(char *out, unsigned char id, unsigned char val){ +void ataPrintSmartAttribName(char *out, unsigned char id, unsigned char *definitions){ char *name; + unsigned char val; + + // If no data array, use default interpretations + if (definitions) + val=definitions[id]; + else + val=0; + switch (id){ case 1: diff --git a/sm5/atacmds.cpp b/sm5/atacmds.cpp index d70e2aa13..315549631 100644 --- a/sm5/atacmds.cpp +++ b/sm5/atacmds.cpp @@ -33,7 +33,7 @@ #include "extern.h" #include "utility.h" -const char *atacmds_c_cvsid="$Id: atacmds.cpp,v 1.114 2003/08/05 16:27:43 ballen4705 Exp $" ATACMDS_H_CVSID ESCALADE_H_CVSID EXTERN_H_CVSID UTILITY_H_CVSID; +const char *atacmds_c_cvsid="$Id: atacmds.cpp,v 1.115 2003/08/13 12:33:22 ballen4705 Exp $" ATACMDS_H_CVSID ESCALADE_H_CVSID EXTERN_H_CVSID UTILITY_H_CVSID; // for passing global control variables extern smartmonctrl *con; @@ -172,9 +172,18 @@ const char *vendorattributeargs[] = { // This is a utility function for parsing pairs like "9,minutes" or // "220,temp", and putting the correct flag into the attributedefs // array. Returns 1 if problem, 0 if pair has been recongized. -int parse_attribute_def(char *pair, unsigned char *defs){ +int parse_attribute_def(char *pair, unsigned char **defsptr){ int i,j; char temp[32]; + unsigned char *defs; + + // If array does not exist, allocate it + if (!*defsptr && !(*defsptr=(unsigned char *)calloc(MAX_ATTRIBUTE_NUM, 1))){ + pout("Out of memory in parse_attribute_def\n"); + exit(1); + } + + defs=*defsptr; // look along list and see if we find the pair for (i=0; vendorattributeargs[i] && strcmp(pair, vendorattributeargs[i]); i++); @@ -198,17 +207,17 @@ int parse_attribute_def(char *pair, unsigned char *defs){ return 0; case 4: // print all attributes in raw 8-bit form - for (j=0; j<256; j++) + for (j=0; j<MAX_ATTRIBUTE_NUM; j++) defs[j]=253; return 0; case 5: // print all attributes in raw 16-bit form - for (j=0; j<256; j++) + for (j=0; j<MAX_ATTRIBUTE_NUM; j++) defs[j]=254; return 0; case 6: // print all attributes in raw 48-bit form - for (j=0; j<256; j++) + for (j=0; j<MAX_ATTRIBUTE_NUM; j++) defs[j]=255; return 0; case 7: @@ -663,7 +672,7 @@ int smartcommandhandler(int device, smart_command_set command, int select, char pout("\n"); } - if (getsdata && data==NULL){ + if (getsdata && !data){ pout("REPORT-IOCTL: Unable to execute command %s : data destination address is NULL\n", commandstrings[command]); return -1; } @@ -1378,6 +1387,7 @@ long long ataPrintSmartAttribRawValue(char *out, long long rawvalue; unsigned word[3]; int j; + unsigned char select; // convert the six individual bytes to a long long (8 byte) integer. // This is the value that we'll eventually return. @@ -1400,8 +1410,14 @@ long long ataPrintSmartAttribRawValue(char *out, word[j] |= attribute->raw[2*j]; } + // if no data array, Attributes have default interpretations + if (defs) + select=defs[attribute->id]; + else + select=0; + // Print six one-byte quantities. - if (defs[attribute->id]==253){ + if (select==253){ for (j=0; j<5; j++) out+=sprintf(out, "%d ", attribute->raw[5-j]); out+=sprintf(out, "%d ", attribute->raw[0]); @@ -1409,13 +1425,13 @@ long long ataPrintSmartAttribRawValue(char *out, } // Print three two-byte quantities - if (defs[attribute->id]==254){ + if (select==254){ out+=sprintf(out, "%d %d %d", word[2], word[1], word[0]); return rawvalue; } // Print one six-byte quantity - if (defs[attribute->id]==255){ + if (select==255){ out+=sprintf(out, "%llu", rawvalue); return rawvalue; } @@ -1432,20 +1448,20 @@ long long ataPrintSmartAttribRawValue(char *out, break; // Power on time case 9: - if (defs[9]==1){ + if (select==1){ // minutes long long tmp1=rawvalue/60; long long tmp2=rawvalue%60; out+=sprintf(out, "%lluh+%02llum", tmp1, tmp2); } - else if (defs[9]==3){ + else if (select==3){ // seconds long long hours=rawvalue/3600; long long minutes=(rawvalue-3600*hours)/60; long long seconds=rawvalue%60; out+=sprintf(out, "%lluh+%02llum+%02llus", hours, minutes, seconds); } - else if (defs[9]==4){ + else if (select==4){ // 30-second counter long long tmp1=rawvalue/120; long long tmp2=(rawvalue-120*tmp1)/2; @@ -1457,7 +1473,7 @@ long long ataPrintSmartAttribRawValue(char *out, break; // Load unload cycles case 193: - if (defs[193]==1){ + if (select==1){ // loadunload long load =attribute->raw[0] + (attribute->raw[1]<<8) + (attribute->raw[2]<<16); long unload=attribute->raw[3] + (attribute->raw[4]<<8) + (attribute->raw[5]<<16); @@ -1469,13 +1485,13 @@ long long ataPrintSmartAttribRawValue(char *out, break; // Temperature case 194: - if (defs[194]==1){ + if (select==1){ // ten times temperature in Celsius int deg=word[0]/10; int tenths=word[0]%10; out+=sprintf(out, "%d.%d", deg, tenths); } - else if (defs[194]==2) + else if (select==2) // unknown attribute out+=sprintf(out, "%llu", rawvalue); else { @@ -1498,8 +1514,16 @@ long long ataPrintSmartAttribRawValue(char *out, // manufacturers use different attribute IDs for an attribute with the // same name. The variable val should contain a non-zero value if a particular // attributes has a non-default interpretation. -void ataPrintSmartAttribName(char *out, unsigned char id, unsigned char val){ +void ataPrintSmartAttribName(char *out, unsigned char id, unsigned char *definitions){ char *name; + unsigned char val; + + // If no data array, use default interpretations + if (definitions) + val=definitions[id]; + else + val=0; + switch (id){ case 1: diff --git a/sm5/atacmds.h b/sm5/atacmds.h index ec0ba2f4b..2c742c319 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.48 2003/08/05 16:27:43 ballen4705 Exp $\n" +#define ATACMDS_H_CVSID "$Id: atacmds.h,v 1.49 2003/08/13 12:33:23 ballen4705 Exp $\n" #endif #include <sys/ioctl.h> @@ -437,7 +437,7 @@ long long ataPrintSmartAttribRawValue(char *out, // Prints Attribute Name for standard SMART attributes. Writes a // 30 byte string with attribute name into output -void ataPrintSmartAttribName(char *output, unsigned char id, unsigned char val); +void ataPrintSmartAttribName(char *output, unsigned char id, unsigned char *definitions); // This checks the n'th attribute in the attribute list, NOT the // attribute with id==n. If the attribute does not exist, or the @@ -455,16 +455,21 @@ int ataCheckAttribute(struct ata_smart_values *data, // Structure with the incorrect checksum. void checksumwarning(const char *string); +#define MAX_ATTRIBUTE_NUM 256 + extern const char *vendorattributeargs[]; // function to parse pairs like "9,minutes" or "220,temp". See end of // extern.h for definition of defs[]. Returns 0 if pair recognized, -// else 1 if there is a problem. -int parse_attribute_def(char *pair, unsigned char *defs); +// else 1 if there is a problem. Allocates memory for array if the +// array address is *defs==NULL. +int parse_attribute_def(char *pair, unsigned char **defs); // Function to return a string containing a list of the arguments in // vendorattributeargs[]. Returns NULL if the required memory can't // be allocated. char *create_vendor_attribute_arg_list(void); + + #endif /* _ATACMDS_H_ */ diff --git a/sm5/ataprint.c b/sm5/ataprint.c index 355f7ead7..70f4bdf60 100644 --- a/sm5/ataprint.c +++ b/sm5/ataprint.c @@ -34,7 +34,7 @@ #include "utility.h" #include "knowndrives.h" -const char *ataprint_c_cvsid="$Id: ataprint.c,v 1.96 2003/07/22 14:08:58 ballen4705 Exp $" +const char *ataprint_c_cvsid="$Id: ataprint.c,v 1.97 2003/08/13 12:33:23 ballen4705 Exp $" ATACMDNAMES_H_CVSID ATACMDS_H_CVSID ATAPRINT_H_CVSID EXTERN_H_CVSID KNOWNDRIVES_H_CVSID SMARTCTL_H_CVSID UTILITY_H_CVSID; // for passing global control variables @@ -452,7 +452,7 @@ void PrintSmartAttribWithThres (struct ata_smart_values *data, status=" -"; // Print name of attribute - ataPrintSmartAttribName(attributename,disk->id, con->attributedefs[disk->id]); + ataPrintSmartAttribName(attributename,disk->id, con->attributedefs); pout("%-28s",attributename); // printing line for each valid attribute @@ -470,8 +470,8 @@ void PrintSmartAttribWithThres (struct ata_smart_values *data, // print a warning if there is inconsistency here! if (disk->id != thre->id){ char atdat[64],atthr[64]; - ataPrintSmartAttribName(atdat, disk->id, con->attributedefs[disk->id]); - ataPrintSmartAttribName(atthr, thre->id, con->attributedefs[thre->id]); + ataPrintSmartAttribName(atdat, disk->id, con->attributedefs); + ataPrintSmartAttribName(atthr, thre->id, con->attributedefs); pout("%-28s<== Data Page | WARNING: PREVIOUS ATTRIBUTE HAS TWO\n",atdat); pout("%-28s<== Threshold Page | INCONSISTENT IDENTITIES IN THE DATA\n",atthr); } @@ -873,8 +873,15 @@ int ataPrintMain (int fd){ } // Use preset vendor attribute options unless user has requested otherwise. - if (!con->ignorepresets) - applypresets(&drive, con->attributedefs, con); + if (!con->ignorepresets){ + unsigned char *charptr; + if ((charptr=con->attributedefs)) + applypresets(&drive, &charptr, con); + else { + pout("Fatal internal error in ataPrintMain()\n"); + exit(1); + } + } // Print most drive identity information if requested if (con->driveinfo){ diff --git a/sm5/ataprint.cpp b/sm5/ataprint.cpp index c1b788523..0e1b222c0 100644 --- a/sm5/ataprint.cpp +++ b/sm5/ataprint.cpp @@ -34,7 +34,7 @@ #include "utility.h" #include "knowndrives.h" -const char *ataprint_c_cvsid="$Id: ataprint.cpp,v 1.96 2003/07/22 14:08:58 ballen4705 Exp $" +const char *ataprint_c_cvsid="$Id: ataprint.cpp,v 1.97 2003/08/13 12:33:23 ballen4705 Exp $" ATACMDNAMES_H_CVSID ATACMDS_H_CVSID ATAPRINT_H_CVSID EXTERN_H_CVSID KNOWNDRIVES_H_CVSID SMARTCTL_H_CVSID UTILITY_H_CVSID; // for passing global control variables @@ -452,7 +452,7 @@ void PrintSmartAttribWithThres (struct ata_smart_values *data, status=" -"; // Print name of attribute - ataPrintSmartAttribName(attributename,disk->id, con->attributedefs[disk->id]); + ataPrintSmartAttribName(attributename,disk->id, con->attributedefs); pout("%-28s",attributename); // printing line for each valid attribute @@ -470,8 +470,8 @@ void PrintSmartAttribWithThres (struct ata_smart_values *data, // print a warning if there is inconsistency here! if (disk->id != thre->id){ char atdat[64],atthr[64]; - ataPrintSmartAttribName(atdat, disk->id, con->attributedefs[disk->id]); - ataPrintSmartAttribName(atthr, thre->id, con->attributedefs[thre->id]); + ataPrintSmartAttribName(atdat, disk->id, con->attributedefs); + ataPrintSmartAttribName(atthr, thre->id, con->attributedefs); pout("%-28s<== Data Page | WARNING: PREVIOUS ATTRIBUTE HAS TWO\n",atdat); pout("%-28s<== Threshold Page | INCONSISTENT IDENTITIES IN THE DATA\n",atthr); } @@ -873,8 +873,15 @@ int ataPrintMain (int fd){ } // Use preset vendor attribute options unless user has requested otherwise. - if (!con->ignorepresets) - applypresets(&drive, con->attributedefs, con); + if (!con->ignorepresets){ + unsigned char *charptr; + if ((charptr=con->attributedefs)) + applypresets(&drive, &charptr, con); + else { + pout("Fatal internal error in ataPrintMain()\n"); + exit(1); + } + } // Print most drive identity information if requested if (con->driveinfo){ diff --git a/sm5/knowndrives.c b/sm5/knowndrives.c index 84fdb7d6d..63693d975 100644 --- a/sm5/knowndrives.c +++ b/sm5/knowndrives.c @@ -24,7 +24,7 @@ #include "knowndrives.h" #include "utility.h" -const char *knowndrives_c_cvsid="$Id: knowndrives.c,v 1.35 2003/08/11 13:25:20 ballen4705 Exp $" ATACMDS_H_CVSID ATAPRINT_H_CVSID KNOWNDRIVES_H_CVSID UTILITY_H_CVSID; +const char *knowndrives_c_cvsid="$Id: knowndrives.c,v 1.36 2003/08/13 12:33:23 ballen4705 Exp $" ATACMDS_H_CVSID ATAPRINT_H_CVSID KNOWNDRIVES_H_CVSID UTILITY_H_CVSID; #define MODEL_STRING_LENGTH 40 #define FIRMWARE_STRING_LENGTH 8 @@ -89,6 +89,8 @@ const unsigned char vendoropts_Hitachi_DK23EA[][2] = { {0,0} }; +const char same_as_minus_F[]="Fixes byte order in some SMART data (same as -F samsung)"; +const char may_need_minus_F_disabled[]="Contact developers; may need -F samsung disabled"; /* Special-purpose functions for use in knowndrives[]. */ void specialpurpose_reverse_samsung(smartmonctrl *con) @@ -148,15 +150,15 @@ const drivesettings knowndrives[] = { NULL, vendoropts_Samsung_SV4012H, specialpurpose_reverse_samsung, - "Fixes byte order in some SMART data (same as -F)" + same_as_minus_F }, { // Samsung SV4012H (all other firmware) "^SAMSUNG SV4012H$", ".*", - "Contact developers; may need -F disabled", + may_need_minus_F_disabled, vendoropts_Samsung_SV4012H, specialpurpose_reverse_samsung, - "Fixes byte order in some SMART data (same as -F)" + same_as_minus_F }, { // Samsung SV1204H (known firmware) "^SAMSUNG SV1204H$", @@ -164,15 +166,15 @@ const drivesettings knowndrives[] = { NULL, vendoropts_Samsung_SV1204H, specialpurpose_reverse_samsung, - "Fixes byte order in some SMART data (same as -F)" + same_as_minus_F }, { //Samsung SV1204H (all other firmware) "^SAMSUNG SV1204H$", ".*", - "Contact developers; may need -F disabled", + may_need_minus_F_disabled, vendoropts_Samsung_SV1204H, specialpurpose_reverse_samsung, - "Fixes byte order in some SMART data (same as -F)" + same_as_minus_F }, { // Samsung SV0412H (known firmware) "^SAMSUNG SV0412H$", @@ -180,15 +182,15 @@ const drivesettings knowndrives[] = { NULL, vendoropts_Samsung_SV1204H, specialpurpose_reverse_samsung, - "Fixes byte order in some SMART data (same as -F)" + same_as_minus_F }, { // Samsung SV0412H (all other firmware) "^SAMSUNG SV0412H$", ".*", - "Contact developers; may need -F disabled", + may_need_minus_F_disabled, vendoropts_Samsung_SV1204H, specialpurpose_reverse_samsung, - "Fixes byte order in some SMART data (same as -F)" + same_as_minus_F }, { //Samsung SP1604N, tested with FW TM100-23 "^SAMSUNG SP1604N$", @@ -205,20 +207,10 @@ const drivesettings knowndrives[] = { NULL, NULL }, - - - - - - - - - - { // Samsung ALL OTHER DRIVES "^SAMSUNG.*", ".*", - "Contact developers; may need -F enabled.\n", + "Contact developers; may need -F samsung enabled.\n", NULL, NULL, NULL }, { // Maxtor 6L080J4 and 4K080H4 @@ -361,12 +353,17 @@ void showonepreset(const drivesettings *drivetable){ if (presets && (*presets)[0]) while (1) { char out[64]; const int attr = (*presets)[0], val = (*presets)[1]; - + unsigned char fakearray[MAX_ATTRIBUTE_NUM]; + // if we are at the end of the attribute list, break out if (!attr) break; - ataPrintSmartAttribName(out, attr, val); + // This is a hack. ataPrintSmartAttribName() needs a pointer to an + // "array" to dereference, so we provide such a pointer. + fakearray[attr]=val; + ataPrintSmartAttribName(out, attr, fakearray); + // Use leading zeros instead of spaces so that everything lines up. out[0] = (out[0] == ' ') ? '0' : out[0]; out[1] = (out[1] == ' ') ? '0' : out[1]; @@ -442,11 +439,19 @@ void showpresets(const struct hd_driveid *drive){ // (if any) for the given drive in knowndrives[]. Values that have // already been set in opts will not be changed. Returns <0 if drive // not recognized else index >=0 into drive database. -int applypresets(const struct hd_driveid *drive, unsigned char opts[256], +int applypresets(const struct hd_driveid *drive, unsigned char **optsptr, smartmonctrl *con) { int i; + unsigned char *opts; char model[MODEL_STRING_LENGTH+1], firmware[FIRMWARE_STRING_LENGTH+1]; + if (*optsptr==NULL && !(*optsptr=(unsigned char *)calloc(MAX_ATTRIBUTE_NUM,1))){ + pout("Unable to allocate memory in applypresets()"); + exit(1); + } + + opts=*optsptr; + // get the drive's model/firmware strings formatdriveidstring(model, drive->model, MODEL_STRING_LENGTH); formatdriveidstring(firmware, drive->fw_rev, FIRMWARE_STRING_LENGTH); diff --git a/sm5/knowndrives.cpp b/sm5/knowndrives.cpp index baf6ee05f..84016614e 100644 --- a/sm5/knowndrives.cpp +++ b/sm5/knowndrives.cpp @@ -24,7 +24,7 @@ #include "knowndrives.h" #include "utility.h" -const char *knowndrives_c_cvsid="$Id: knowndrives.cpp,v 1.35 2003/08/11 13:25:20 ballen4705 Exp $" ATACMDS_H_CVSID ATAPRINT_H_CVSID KNOWNDRIVES_H_CVSID UTILITY_H_CVSID; +const char *knowndrives_c_cvsid="$Id: knowndrives.cpp,v 1.36 2003/08/13 12:33:23 ballen4705 Exp $" ATACMDS_H_CVSID ATAPRINT_H_CVSID KNOWNDRIVES_H_CVSID UTILITY_H_CVSID; #define MODEL_STRING_LENGTH 40 #define FIRMWARE_STRING_LENGTH 8 @@ -89,6 +89,8 @@ const unsigned char vendoropts_Hitachi_DK23EA[][2] = { {0,0} }; +const char same_as_minus_F[]="Fixes byte order in some SMART data (same as -F samsung)"; +const char may_need_minus_F_disabled[]="Contact developers; may need -F samsung disabled"; /* Special-purpose functions for use in knowndrives[]. */ void specialpurpose_reverse_samsung(smartmonctrl *con) @@ -148,15 +150,15 @@ const drivesettings knowndrives[] = { NULL, vendoropts_Samsung_SV4012H, specialpurpose_reverse_samsung, - "Fixes byte order in some SMART data (same as -F)" + same_as_minus_F }, { // Samsung SV4012H (all other firmware) "^SAMSUNG SV4012H$", ".*", - "Contact developers; may need -F disabled", + may_need_minus_F_disabled, vendoropts_Samsung_SV4012H, specialpurpose_reverse_samsung, - "Fixes byte order in some SMART data (same as -F)" + same_as_minus_F }, { // Samsung SV1204H (known firmware) "^SAMSUNG SV1204H$", @@ -164,15 +166,15 @@ const drivesettings knowndrives[] = { NULL, vendoropts_Samsung_SV1204H, specialpurpose_reverse_samsung, - "Fixes byte order in some SMART data (same as -F)" + same_as_minus_F }, { //Samsung SV1204H (all other firmware) "^SAMSUNG SV1204H$", ".*", - "Contact developers; may need -F disabled", + may_need_minus_F_disabled, vendoropts_Samsung_SV1204H, specialpurpose_reverse_samsung, - "Fixes byte order in some SMART data (same as -F)" + same_as_minus_F }, { // Samsung SV0412H (known firmware) "^SAMSUNG SV0412H$", @@ -180,15 +182,15 @@ const drivesettings knowndrives[] = { NULL, vendoropts_Samsung_SV1204H, specialpurpose_reverse_samsung, - "Fixes byte order in some SMART data (same as -F)" + same_as_minus_F }, { // Samsung SV0412H (all other firmware) "^SAMSUNG SV0412H$", ".*", - "Contact developers; may need -F disabled", + may_need_minus_F_disabled, vendoropts_Samsung_SV1204H, specialpurpose_reverse_samsung, - "Fixes byte order in some SMART data (same as -F)" + same_as_minus_F }, { //Samsung SP1604N, tested with FW TM100-23 "^SAMSUNG SP1604N$", @@ -205,20 +207,10 @@ const drivesettings knowndrives[] = { NULL, NULL }, - - - - - - - - - - { // Samsung ALL OTHER DRIVES "^SAMSUNG.*", ".*", - "Contact developers; may need -F enabled.\n", + "Contact developers; may need -F samsung enabled.\n", NULL, NULL, NULL }, { // Maxtor 6L080J4 and 4K080H4 @@ -361,12 +353,17 @@ void showonepreset(const drivesettings *drivetable){ if (presets && (*presets)[0]) while (1) { char out[64]; const int attr = (*presets)[0], val = (*presets)[1]; - + unsigned char fakearray[MAX_ATTRIBUTE_NUM]; + // if we are at the end of the attribute list, break out if (!attr) break; - ataPrintSmartAttribName(out, attr, val); + // This is a hack. ataPrintSmartAttribName() needs a pointer to an + // "array" to dereference, so we provide such a pointer. + fakearray[attr]=val; + ataPrintSmartAttribName(out, attr, fakearray); + // Use leading zeros instead of spaces so that everything lines up. out[0] = (out[0] == ' ') ? '0' : out[0]; out[1] = (out[1] == ' ') ? '0' : out[1]; @@ -442,11 +439,19 @@ void showpresets(const struct hd_driveid *drive){ // (if any) for the given drive in knowndrives[]. Values that have // already been set in opts will not be changed. Returns <0 if drive // not recognized else index >=0 into drive database. -int applypresets(const struct hd_driveid *drive, unsigned char opts[256], +int applypresets(const struct hd_driveid *drive, unsigned char **optsptr, smartmonctrl *con) { int i; + unsigned char *opts; char model[MODEL_STRING_LENGTH+1], firmware[FIRMWARE_STRING_LENGTH+1]; + if (*optsptr==NULL && !(*optsptr=(unsigned char *)calloc(MAX_ATTRIBUTE_NUM,1))){ + pout("Unable to allocate memory in applypresets()"); + exit(1); + } + + opts=*optsptr; + // get the drive's model/firmware strings formatdriveidstring(model, drive->model, MODEL_STRING_LENGTH); formatdriveidstring(firmware, drive->fw_rev, FIRMWARE_STRING_LENGTH); diff --git a/sm5/knowndrives.h b/sm5/knowndrives.h index afeeb2565..01e18c924 100644 --- a/sm5/knowndrives.h +++ b/sm5/knowndrives.h @@ -20,7 +20,7 @@ #ifndef __KNOWNDRIVES_H_ #define __KNOWNDRIVES_H_ -#define KNOWNDRIVES_H_CVSID "$Id: knowndrives.h,v 1.6 2003/04/20 15:38:38 ballen4705 Exp $\n" +#define KNOWNDRIVES_H_CVSID "$Id: knowndrives.h,v 1.7 2003/08/13 12:33:23 ballen4705 Exp $\n" #include <linux/hdreg.h> #include "extern.h" @@ -76,7 +76,7 @@ void showallpresets(void); // already been set in opts will not be changed. Also sets options in // con. Returns <0 if drive not recognized else index of drive in // database. -int applypresets(const struct hd_driveid *drive, unsigned char opts[256], +int applypresets(const struct hd_driveid *drive, unsigned char **opts, smartmonctrl *con); #endif diff --git a/sm5/smartctl.c b/sm5/smartctl.c index 3eca064e3..a0ccde35f 100644 --- a/sm5/smartctl.c +++ b/sm5/smartctl.c @@ -43,7 +43,7 @@ #include "utility.h" extern const char *atacmdnames_c_cvsid, *atacmds_c_cvsid, *ataprint_c_cvsid, *escalade_c_cvsid, *knowndrives_c_cvsid, *scsicmds_c_cvsid, *scsiprint_c_cvsid, *utility_c_cvsid; -const char* smartctl_c_cvsid="$Id: smartctl.c,v 1.84 2003/08/12 03:50:06 ballen4705 Exp $" +const char* smartctl_c_cvsid="$Id: smartctl.c,v 1.85 2003/08/13 12:33:23 ballen4705 Exp $" ATACMDS_H_CVSID ATAPRINT_H_CVSID EXTERN_H_CVSID KNOWNDRIVES_H_CVSID SCSICMDS_H_CVSID SCSIPRINT_H_CVSID SMARTCTL_H_CVSID UTILITY_H_CVSID; // This is a block containing all the "control variables". We declare @@ -237,11 +237,8 @@ void Usage (void){ } /* Returns a pointer to a static string containing a formatted list of the valid - arguments to the option opt or NULL on failure. */ + arguments to the option opt or NULL on failure. Note 'v' case different */ const char *getvalidarglist(char opt) { - static char *v_list = NULL; - char *s; - switch (opt) { case 'q': return "errorsonly, silent"; @@ -259,16 +256,6 @@ const char *getvalidarglist(char opt) { return "on, off"; case 'l': return "error, selftest, directory"; - case 'v': - if (v_list) - return v_list; - if (!(s = create_vendor_attribute_arg_list())) - return NULL; - // Allocate space for tab + "help" + newline + s + terminating 0 - v_list = (char *)malloc(7+strlen(s)); - sprintf(v_list, "\thelp\n%s", s); - free(s); - return v_list; case 'P': return "use, ignore, show, showall"; case 't': @@ -279,6 +266,7 @@ const char *getvalidarglist(char opt) { #endif case 'F': return "none, samsung"; + case 'v': default: return NULL; } @@ -287,22 +275,33 @@ const char *getvalidarglist(char opt) { /* Prints the message "=======> VALID ARGUMENTS ARE: <LIST> <=======\n", where <LIST> is the list of valid arguments for option opt. */ void printvalidarglistmessage(char opt) { - const char *s; - char separator; - - if (!(s = getvalidarglist(opt))) { + char *s; + + if (opt=='v') + s=create_vendor_attribute_arg_list(); + else + s=(char *)getvalidarglist(opt); + + if (!s) { pout("Error whilst constructing argument list for option %c", opt); return; } - + + if (opt=='v'){ + pout("=======> VALID ARGUMENTS ARE:\n\thelp\n%s\n<=======\n", s); + free(s); + } + else { // getvalidarglist() might produce a multiline or single line string. We // need to figure out which to get the formatting right. - separator = strchr(s, '\n') ? '\n' : ' '; + char separator = strchr(s, '\n') ? '\n' : ' '; + pout("=======> VALID ARGUMENTS ARE:%c%s%c<=======\n", separator, (char *)s, separator); + } - pout("=======> VALID ARGUMENTS ARE:%c%s%c<=======\n", separator, (char *)s, - separator); + return; } + unsigned char tryata=0,tryscsi=0; /* Takes command options and sets features to be run */ @@ -310,6 +309,7 @@ void ParseOpts (int argc, char** argv){ int optchar; int badarg; int captive; + unsigned char *charp; extern char *optarg; extern int optopt, optind, opterr; // Please update getvalidarglist() if you edit shortopts @@ -556,7 +556,12 @@ void ParseOpts (int argc, char** argv){ free(s); exit(0); } - if (parse_attribute_def(optarg, con->attributedefs)) + charp=con->attributedefs; + if (!charp){ + pout("Fatal internal error in ParseOpts()\n"); + exit(FAILCMD); + } + if (parse_attribute_def(optarg, &charp)) badarg = TRUE; break; case 'P': diff --git a/sm5/smartctl.cpp b/sm5/smartctl.cpp index bc42dec6a..6089fd728 100644 --- a/sm5/smartctl.cpp +++ b/sm5/smartctl.cpp @@ -43,7 +43,7 @@ #include "utility.h" extern const char *atacmdnames_c_cvsid, *atacmds_c_cvsid, *ataprint_c_cvsid, *escalade_c_cvsid, *knowndrives_c_cvsid, *scsicmds_c_cvsid, *scsiprint_c_cvsid, *utility_c_cvsid; -const char* smartctl_c_cvsid="$Id: smartctl.cpp,v 1.84 2003/08/12 03:50:06 ballen4705 Exp $" +const char* smartctl_c_cvsid="$Id: smartctl.cpp,v 1.85 2003/08/13 12:33:23 ballen4705 Exp $" ATACMDS_H_CVSID ATAPRINT_H_CVSID EXTERN_H_CVSID KNOWNDRIVES_H_CVSID SCSICMDS_H_CVSID SCSIPRINT_H_CVSID SMARTCTL_H_CVSID UTILITY_H_CVSID; // This is a block containing all the "control variables". We declare @@ -237,11 +237,8 @@ void Usage (void){ } /* Returns a pointer to a static string containing a formatted list of the valid - arguments to the option opt or NULL on failure. */ + arguments to the option opt or NULL on failure. Note 'v' case different */ const char *getvalidarglist(char opt) { - static char *v_list = NULL; - char *s; - switch (opt) { case 'q': return "errorsonly, silent"; @@ -259,16 +256,6 @@ const char *getvalidarglist(char opt) { return "on, off"; case 'l': return "error, selftest, directory"; - case 'v': - if (v_list) - return v_list; - if (!(s = create_vendor_attribute_arg_list())) - return NULL; - // Allocate space for tab + "help" + newline + s + terminating 0 - v_list = (char *)malloc(7+strlen(s)); - sprintf(v_list, "\thelp\n%s", s); - free(s); - return v_list; case 'P': return "use, ignore, show, showall"; case 't': @@ -279,6 +266,7 @@ const char *getvalidarglist(char opt) { #endif case 'F': return "none, samsung"; + case 'v': default: return NULL; } @@ -287,22 +275,33 @@ const char *getvalidarglist(char opt) { /* Prints the message "=======> VALID ARGUMENTS ARE: <LIST> <=======\n", where <LIST> is the list of valid arguments for option opt. */ void printvalidarglistmessage(char opt) { - const char *s; - char separator; - - if (!(s = getvalidarglist(opt))) { + char *s; + + if (opt=='v') + s=create_vendor_attribute_arg_list(); + else + s=(char *)getvalidarglist(opt); + + if (!s) { pout("Error whilst constructing argument list for option %c", opt); return; } - + + if (opt=='v'){ + pout("=======> VALID ARGUMENTS ARE:\n\thelp\n%s\n<=======\n", s); + free(s); + } + else { // getvalidarglist() might produce a multiline or single line string. We // need to figure out which to get the formatting right. - separator = strchr(s, '\n') ? '\n' : ' '; + char separator = strchr(s, '\n') ? '\n' : ' '; + pout("=======> VALID ARGUMENTS ARE:%c%s%c<=======\n", separator, (char *)s, separator); + } - pout("=======> VALID ARGUMENTS ARE:%c%s%c<=======\n", separator, (char *)s, - separator); + return; } + unsigned char tryata=0,tryscsi=0; /* Takes command options and sets features to be run */ @@ -310,6 +309,7 @@ void ParseOpts (int argc, char** argv){ int optchar; int badarg; int captive; + unsigned char *charp; extern char *optarg; extern int optopt, optind, opterr; // Please update getvalidarglist() if you edit shortopts @@ -556,7 +556,12 @@ void ParseOpts (int argc, char** argv){ free(s); exit(0); } - if (parse_attribute_def(optarg, con->attributedefs)) + charp=con->attributedefs; + if (!charp){ + pout("Fatal internal error in ParseOpts()\n"); + exit(FAILCMD); + } + if (parse_attribute_def(optarg, &charp)) badarg = TRUE; break; case 'P': diff --git a/sm5/smartd.8 b/sm5/smartd.8 index 28e169633..fe3c1e507 100644 --- a/sm5/smartd.8 +++ b/sm5/smartd.8 @@ -1,6 +1,6 @@ \# Copyright (C) 2002-3 Bruce Allen <smartmontools-support@lists.sourceforge.net> \# -\# $Id: smartd.8,v 1.104 2003/08/07 09:58:02 ballen4705 Exp $ +\# $Id: smartd.8,v 1.105 2003/08/13 12:33:23 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/08/07 09:58:02 $" "smartmontools-5.1" +.TH SMARTD 8 "$Date: 2003/08/13 12:33:23 $" "smartmontools-5.1" .SH NAME smartd \- SMART Disk Monitoring Daemon .SH SYNOPSIS @@ -105,10 +105,10 @@ to see the available options. .B \-d, \-\-debug Runs .B smartd -in ""debug"" mode. In this mode, it does not -.B fork -(2) and displays status information to STDOUT. It also prints more -verbose information about what it is doing. +in \(dqdebug\(dq mode. In this mode, it displays status information to +STDOUT rather than logging it in SYSLOG and does not \fBfork(2)\fP. +It also prints more verbose information about what it is doing than +when operating in \(dqdaemon\(dq mode. .TP .B \-D, \-\-showdirectives Prints a list (to STDOUT) of all the possible Directives which may @@ -152,7 +152,7 @@ containing the Process ID number (PID). To avoid symlink attacks make sure the directory to which pidfile is written is only writeable for root. Without this option, -or if the --debug option is given, no PID file is written on startup. +or if the \-\-debug option is given, no PID file is written on startup. If .B smartd is killed with a maskable signal then the pidfile is removed. @@ -576,9 +576,9 @@ command-line option.] .B \-f Check for 'failure' of any Usage Attributes. If these Attributes are less than or equal to the threshold, it does NOT -indicate imminent disk failure. It ""indicates an advisory condition +indicate imminent disk failure. It \(dqindicates an advisory condition where the usage or age of the device has exceeded its intended design -life period."" [Please see the +life period.\(dq [Please see the .B smartctl \-A command-line option.] @@ -1322,4 +1322,4 @@ smartmontools home page at \fBhttp://smartmontools.sourceforge.net/\fP . .SH CVS ID OF THIS PAGE: -$Id: smartd.8,v 1.104 2003/08/07 09:58:02 ballen4705 Exp $ +$Id: smartd.8,v 1.105 2003/08/13 12:33:23 ballen4705 Exp $ diff --git a/sm5/smartd.c b/sm5/smartd.c index 3bca96ba9..1cc878c1e 100644 --- a/sm5/smartd.c +++ b/sm5/smartd.c @@ -50,7 +50,7 @@ #include "utility.h" extern const char *atacmdnames_c_cvsid, *atacmds_c_cvsid, *ataprint_c_cvsid, *escalade_c_cvsid, *knowndrives_c_cvsid, *scsicmds_c_cvsid, *utility_c_cvsid; -const char *smartd_c_cvsid="$Id: smartd.c,v 1.188 2003/08/11 20:43:05 ballen4705 Exp $" +const char *smartd_c_cvsid="$Id: smartd.c,v 1.189 2003/08/13 12:33:23 ballen4705 Exp $" ATACMDS_H_CVSID ATAPRINT_H_CVSID EXTERN_H_CVSID KNOWNDRIVES_H_CVSID SCSICMDS_H_CVSID SMARTD_H_CVSID UTILITY_H_CVSID; // Forward declarations @@ -339,7 +339,7 @@ void pout(char *fmt, ...){ // tell user that we ignore HUP signals void huphandler(int sig){ - printout(LOG_CRIT,"HUP ignored: smartd does NOT re-read /etc/smartd.conf.\n"); + printout(LOG_INFO,"HUP ignored: smartd does NOT re-read /etc/smartd.conf.\n"); return; } @@ -619,8 +619,9 @@ int atadevicescan(cfgfile *cfg){ // options unless user has requested otherwise. if (!cfg->ignorepresets){ - // do whatever applypresets decides to do - if (applypresets(&drive, cfg->attributedefs, con)<0) + // do whatever applypresets decides to do. Will allocate memory if + // cfg->attributedefs if needed. + if (applypresets(&drive, &cfg->attributedefs, con)<0) printout(LOG_INFO, "Device: %s, not found in smartd database.\n", name); else printout(LOG_INFO, "Device: %s, found in smartd database.\n", name); @@ -886,8 +887,8 @@ static int scsidevicescan(cfgfile *cfg) cfg->tryscsi = 1; // get rid of allocated memory only needed for ATA devices - cfg->monitorattflags = checkfree(cfg->monitorattflags); - cfg->attributedefs = checkfree(cfg->attributedefs); + cfg->monitorattflags = freenonzero(cfg->monitorattflags); + cfg->attributedefs = freenonzero(cfg->attributedefs); cfg->smartval = freenonzero(cfg->smartval); cfg->smartthres = freenonzero(cfg->smartthres); @@ -960,12 +961,31 @@ int ataCompareSmartValues(changedattribute_t *delta, // sorting functions! Entry is ZERO <==> the attribute ON. Calling // with set=0 tells you if the attribute is being tracked or not. // Calling with set=1 turns the attribute OFF. -int isattoff(unsigned char attr,unsigned char *data, int set){ - // locate correct attribute +int isattoff(unsigned char attr, unsigned char **datap, int set, int which){ + unsigned char *data; int loc=attr>>3; int bit=attr & 0x07; unsigned char mask=0x01<<bit; + if (which>=NMONITOR){ + printout(LOG_CRIT, "Internal error in isattoff(). which == %d\n", which); + exit(EXIT_NOMEM); + } + + if (*datap == NULL){ + // null data implies Attributes are off... + if (!set) + return 1; + + // we are writing + if (!(*datap=calloc(NMONITOR*32, 1))){ + printout(LOG_CRIT,"No memory to create monattflags\n"); + exit(EXIT_NOMEM); + } + } + + data=*datap+which*32; + // attribute zero is always OFF if (!attr) return 1; @@ -1037,11 +1057,11 @@ int ataCheckDevice(cfgfile *cfg){ // are we ignoring failures of this attribute? att *= -1; - if (!isattoff(att, cfg->monitorattflags, 0)){ + if (!isattoff(att, &cfg->monitorattflags, 0, MONITOR_FAILUSE)){ char attname[64], *loc=attname; // get attribute name & skip white space - ataPrintSmartAttribName(loc, att, cfg->attributedefs[att]); + ataPrintSmartAttribName(loc, att, cfg->attributedefs); while (*loc && *loc==' ') loc++; // warning message @@ -1058,19 +1078,19 @@ int ataCheckDevice(cfgfile *cfg){ // 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)) + if (!delta.sameraw && delta.newval==delta.oldval && !isattoff(id, &cfg->monitorattflags, 0, MONITOR_RAW)) continue; // are we tracking this attribute? - if (!isattoff(id, cfg->monitorattflags+32, 0)){ + if (!isattoff(id, &cfg->monitorattflags, 0, MONITOR_IGNORE)){ char newrawstring[64], oldrawstring[64], attname[64], *loc=attname; // get attribute name, skip spaces - ataPrintSmartAttribName(loc, id, cfg->attributedefs[id]); + ataPrintSmartAttribName(loc, id, cfg->attributedefs); while (*loc && *loc==' ') loc++; // has the user asked for us to print raw values? - if (isattoff(id, cfg->monitorattflags+64, 0)) { + if (isattoff(id, &cfg->monitorattflags, 0, MONITOR_RAWPRINT)) { // get raw values (as a string) and add to printout char rawstring[64]; ataPrintSmartAttribRawValue(rawstring, curval.vendor_attributes+i, cfg->attributedefs); @@ -1587,23 +1607,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->monitorattflags,1); + isattoff(val, &cfg->monitorattflags, 1, MONITOR_FAILUSE); break; case 'I': // ignore attribute for tracking purposes val=inttoken(arg=strtok(NULL,delim), name, token, lineno, CONFIGFILE, 1, 255); - isattoff(val,cfg->monitorattflags+32,1); + isattoff(val, &cfg->monitorattflags, 1, MONITOR_IGNORE); 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); + isattoff(val, &cfg->monitorattflags, 1, MONITOR_RAWPRINT); 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); + isattoff(val, &cfg->monitorattflags, 1, MONITOR_RAWPRINT); + isattoff(val, &cfg->monitorattflags, 1, MONITOR_RAW); break; case 'm': // send email to address that follows @@ -1624,7 +1644,7 @@ int parsetoken(char *token,cfgfile *cfg){ // non-default vendor-specific attribute meaning if ((arg=strtok(NULL,delim)) == NULL) { missingarg = 1; - } else if (parse_attribute_def(arg, cfg->attributedefs)){ + } else if (parse_attribute_def(arg, &cfg->attributedefs)){ badarg = 1; } break; @@ -1685,19 +1705,20 @@ cfgfile *createcfgentry(cfgfile *original){ // if structure had data, copy it if (original) memcpy(add, original, sizeof(cfgfile)); - - // Always make this storage - if ( - !(add->monitorattflags=(unsigned char *)calloc(NMONITOR*32,1)) || - !(add->attributedefs=(unsigned char *)calloc(256,1)) - ) goto badexit; - - if (original){ - memcpy(add->attributedefs, original->attributedefs, 256); - memcpy(add->monitorattflags, original->monitorattflags, NMONITOR*32); + + // make private copies of these ONLY if they are in use + if (add->attributedefs) { + if (!(add->attributedefs=(unsigned char *)calloc(MAX_ATTRIBUTE_NUM,1))) + goto badexit; + memcpy(add->attributedefs, original->attributedefs, MAX_ATTRIBUTE_NUM); + } + + if (add->monitorattflags) { + if (!(add->monitorattflags=(unsigned char *)calloc(NMONITOR*32, 1))) + goto badexit; + memcpy(add->monitorattflags, original->monitorattflags, NMONITOR*32); } - // make private copies of these ONLY if they are used if (add->name && !(add->name=strdup(add->name)) ) goto badexit; @@ -1727,19 +1748,19 @@ cfgfile *createcfgentry(cfgfile *original){ // Removes config file entry, freeing all memory cfgfile *rmconfigentry(cfgfile *original){ - + if (!original){ printout(LOG_CRIT,"Error - rmconfigentry() called with NULL pointer argument\n"); exit(EXIT_NOMEM); } - - freenonzero(original->smartthres); - freenonzero(original->smartval); - freenonzero(original->address); - freenonzero(original->emailcmdline); - freenonzero(original->name); - freenonzero(original->monitorattflags); - freenonzero(original->attributedefs); + + original->smartthres = freenonzero(original->smartthres); + original->smartval = freenonzero(original->smartval); + original->address = freenonzero(original->address); + original->emailcmdline = freenonzero(original->emailcmdline); + original->name = freenonzero(original->name); + original->monitorattflags = freenonzero(original->monitorattflags); + original->attributedefs = freenonzero(original->attributedefs); freenonzero(original); return NULL; @@ -2280,10 +2301,8 @@ int makeconfigentries(int num, char *name, int start){ cfg->tryscsi= (name[5]=='s'); // Remove device name, if it's there, and put in correct one - if (cfg->name) - cfg->name=checkfree(cfg->name); - cfg->name=strdup(name); - if (!cfg->name) { + cfg->name=freenonzero(cfg->name); + if (!(cfg->name=strdup(name))){ printout(LOG_CRIT,"Out of memory making device scan list, %s\n", strerror(errno)); exit(EXIT_NOMEM); } diff --git a/sm5/smartd.cpp b/sm5/smartd.cpp index 29e7f8cb1..129459289 100644 --- a/sm5/smartd.cpp +++ b/sm5/smartd.cpp @@ -50,7 +50,7 @@ #include "utility.h" extern const char *atacmdnames_c_cvsid, *atacmds_c_cvsid, *ataprint_c_cvsid, *escalade_c_cvsid, *knowndrives_c_cvsid, *scsicmds_c_cvsid, *utility_c_cvsid; -const char *smartd_c_cvsid="$Id: smartd.cpp,v 1.188 2003/08/11 20:43:05 ballen4705 Exp $" +const char *smartd_c_cvsid="$Id: smartd.cpp,v 1.189 2003/08/13 12:33:23 ballen4705 Exp $" ATACMDS_H_CVSID ATAPRINT_H_CVSID EXTERN_H_CVSID KNOWNDRIVES_H_CVSID SCSICMDS_H_CVSID SMARTD_H_CVSID UTILITY_H_CVSID; // Forward declarations @@ -339,7 +339,7 @@ void pout(char *fmt, ...){ // tell user that we ignore HUP signals void huphandler(int sig){ - printout(LOG_CRIT,"HUP ignored: smartd does NOT re-read /etc/smartd.conf.\n"); + printout(LOG_INFO,"HUP ignored: smartd does NOT re-read /etc/smartd.conf.\n"); return; } @@ -619,8 +619,9 @@ int atadevicescan(cfgfile *cfg){ // options unless user has requested otherwise. if (!cfg->ignorepresets){ - // do whatever applypresets decides to do - if (applypresets(&drive, cfg->attributedefs, con)<0) + // do whatever applypresets decides to do. Will allocate memory if + // cfg->attributedefs if needed. + if (applypresets(&drive, &cfg->attributedefs, con)<0) printout(LOG_INFO, "Device: %s, not found in smartd database.\n", name); else printout(LOG_INFO, "Device: %s, found in smartd database.\n", name); @@ -886,8 +887,8 @@ static int scsidevicescan(cfgfile *cfg) cfg->tryscsi = 1; // get rid of allocated memory only needed for ATA devices - cfg->monitorattflags = checkfree(cfg->monitorattflags); - cfg->attributedefs = checkfree(cfg->attributedefs); + cfg->monitorattflags = freenonzero(cfg->monitorattflags); + cfg->attributedefs = freenonzero(cfg->attributedefs); cfg->smartval = freenonzero(cfg->smartval); cfg->smartthres = freenonzero(cfg->smartthres); @@ -960,12 +961,31 @@ int ataCompareSmartValues(changedattribute_t *delta, // sorting functions! Entry is ZERO <==> the attribute ON. Calling // with set=0 tells you if the attribute is being tracked or not. // Calling with set=1 turns the attribute OFF. -int isattoff(unsigned char attr,unsigned char *data, int set){ - // locate correct attribute +int isattoff(unsigned char attr, unsigned char **datap, int set, int which){ + unsigned char *data; int loc=attr>>3; int bit=attr & 0x07; unsigned char mask=0x01<<bit; + if (which>=NMONITOR){ + printout(LOG_CRIT, "Internal error in isattoff(). which == %d\n", which); + exit(EXIT_NOMEM); + } + + if (*datap == NULL){ + // null data implies Attributes are off... + if (!set) + return 1; + + // we are writing + if (!(*datap=calloc(NMONITOR*32, 1))){ + printout(LOG_CRIT,"No memory to create monattflags\n"); + exit(EXIT_NOMEM); + } + } + + data=*datap+which*32; + // attribute zero is always OFF if (!attr) return 1; @@ -1037,11 +1057,11 @@ int ataCheckDevice(cfgfile *cfg){ // are we ignoring failures of this attribute? att *= -1; - if (!isattoff(att, cfg->monitorattflags, 0)){ + if (!isattoff(att, &cfg->monitorattflags, 0, MONITOR_FAILUSE)){ char attname[64], *loc=attname; // get attribute name & skip white space - ataPrintSmartAttribName(loc, att, cfg->attributedefs[att]); + ataPrintSmartAttribName(loc, att, cfg->attributedefs); while (*loc && *loc==' ') loc++; // warning message @@ -1058,19 +1078,19 @@ int ataCheckDevice(cfgfile *cfg){ // 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)) + if (!delta.sameraw && delta.newval==delta.oldval && !isattoff(id, &cfg->monitorattflags, 0, MONITOR_RAW)) continue; // are we tracking this attribute? - if (!isattoff(id, cfg->monitorattflags+32, 0)){ + if (!isattoff(id, &cfg->monitorattflags, 0, MONITOR_IGNORE)){ char newrawstring[64], oldrawstring[64], attname[64], *loc=attname; // get attribute name, skip spaces - ataPrintSmartAttribName(loc, id, cfg->attributedefs[id]); + ataPrintSmartAttribName(loc, id, cfg->attributedefs); while (*loc && *loc==' ') loc++; // has the user asked for us to print raw values? - if (isattoff(id, cfg->monitorattflags+64, 0)) { + if (isattoff(id, &cfg->monitorattflags, 0, MONITOR_RAWPRINT)) { // get raw values (as a string) and add to printout char rawstring[64]; ataPrintSmartAttribRawValue(rawstring, curval.vendor_attributes+i, cfg->attributedefs); @@ -1587,23 +1607,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->monitorattflags,1); + isattoff(val, &cfg->monitorattflags, 1, MONITOR_FAILUSE); break; case 'I': // ignore attribute for tracking purposes val=inttoken(arg=strtok(NULL,delim), name, token, lineno, CONFIGFILE, 1, 255); - isattoff(val,cfg->monitorattflags+32,1); + isattoff(val, &cfg->monitorattflags, 1, MONITOR_IGNORE); 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); + isattoff(val, &cfg->monitorattflags, 1, MONITOR_RAWPRINT); 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); + isattoff(val, &cfg->monitorattflags, 1, MONITOR_RAWPRINT); + isattoff(val, &cfg->monitorattflags, 1, MONITOR_RAW); break; case 'm': // send email to address that follows @@ -1624,7 +1644,7 @@ int parsetoken(char *token,cfgfile *cfg){ // non-default vendor-specific attribute meaning if ((arg=strtok(NULL,delim)) == NULL) { missingarg = 1; - } else if (parse_attribute_def(arg, cfg->attributedefs)){ + } else if (parse_attribute_def(arg, &cfg->attributedefs)){ badarg = 1; } break; @@ -1685,19 +1705,20 @@ cfgfile *createcfgentry(cfgfile *original){ // if structure had data, copy it if (original) memcpy(add, original, sizeof(cfgfile)); - - // Always make this storage - if ( - !(add->monitorattflags=(unsigned char *)calloc(NMONITOR*32,1)) || - !(add->attributedefs=(unsigned char *)calloc(256,1)) - ) goto badexit; - - if (original){ - memcpy(add->attributedefs, original->attributedefs, 256); - memcpy(add->monitorattflags, original->monitorattflags, NMONITOR*32); + + // make private copies of these ONLY if they are in use + if (add->attributedefs) { + if (!(add->attributedefs=(unsigned char *)calloc(MAX_ATTRIBUTE_NUM,1))) + goto badexit; + memcpy(add->attributedefs, original->attributedefs, MAX_ATTRIBUTE_NUM); + } + + if (add->monitorattflags) { + if (!(add->monitorattflags=(unsigned char *)calloc(NMONITOR*32, 1))) + goto badexit; + memcpy(add->monitorattflags, original->monitorattflags, NMONITOR*32); } - // make private copies of these ONLY if they are used if (add->name && !(add->name=strdup(add->name)) ) goto badexit; @@ -1727,19 +1748,19 @@ cfgfile *createcfgentry(cfgfile *original){ // Removes config file entry, freeing all memory cfgfile *rmconfigentry(cfgfile *original){ - + if (!original){ printout(LOG_CRIT,"Error - rmconfigentry() called with NULL pointer argument\n"); exit(EXIT_NOMEM); } - - freenonzero(original->smartthres); - freenonzero(original->smartval); - freenonzero(original->address); - freenonzero(original->emailcmdline); - freenonzero(original->name); - freenonzero(original->monitorattflags); - freenonzero(original->attributedefs); + + original->smartthres = freenonzero(original->smartthres); + original->smartval = freenonzero(original->smartval); + original->address = freenonzero(original->address); + original->emailcmdline = freenonzero(original->emailcmdline); + original->name = freenonzero(original->name); + original->monitorattflags = freenonzero(original->monitorattflags); + original->attributedefs = freenonzero(original->attributedefs); freenonzero(original); return NULL; @@ -2280,10 +2301,8 @@ int makeconfigentries(int num, char *name, int start){ cfg->tryscsi= (name[5]=='s'); // Remove device name, if it's there, and put in correct one - if (cfg->name) - cfg->name=checkfree(cfg->name); - cfg->name=strdup(name); - if (!cfg->name) { + cfg->name=freenonzero(cfg->name); + if (!(cfg->name=strdup(name))){ printout(LOG_CRIT,"Out of memory making device scan list, %s\n", strerror(errno)); exit(EXIT_NOMEM); } diff --git a/sm5/smartd.h b/sm5/smartd.h index c953d10f0..b995b7e7d 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.40 2003/08/11 14:31:45 ballen4705 Exp $\n" +#define SMARTD_H_CVSID "$Id: smartd.h,v 1.41 2003/08/13 12:33:23 ballen4705 Exp $\n" #endif // Configuration file @@ -54,9 +54,13 @@ #define TRUE 0x01 #define FALSE 0x00 -// Number of monitoring flags per Attribute. See monitorattflags -// below. +// Number of monitoring flags per Attribute and offsets. See +// monitorattflags below. #define NMONITOR 4 +#define MONITOR_FAILUSE 0 +#define MONITOR_IGNORE 1 +#define MONITOR_RAWPRINT 2 +#define MONITOR_RAW 3 // Exit codes #define EXIT_BADCMD 1 // command line did not parse -- GitLab