diff --git a/sm5/CHANGELOG b/sm5/CHANGELOG index 103a98292fb91e2a5d8488fe6ae439c4e806806a..c3fcca188c6bfc22cb4f66d8d08ed6ef19bc3cf8 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 e4b9a1a80116537cec94e7e85876ec7d1f6928bf..5242c0229d22cd5b2265147b9059c5b841aa4ded 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 594f924e0a16999d8f9fb2c3f4f199289620dcbe..8291fc3dc487cf12b6448a09afcfeef705e82d64 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 9649e55694dfd8e025b2db10bf8a558d92da882e..2630215ea7bdc87120e268876f30a5266fa5caea 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 d70e2aa130f63237c932648ab24bd2b926c84b27..31554963121fa2f0972d856a4c57a638ea8ddf7e 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 ec0ba2f4b2dd06d59f466e1cec051af30c318ab4..2c742c319f4c7c5df0b627d7a3bff2701555dcc6 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 355f7ead76a18e0945b35022ed36809f3df8bae9..70f4bdf609c00af2faf24df928abec7c5f2ca504 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 c1b78852352aeab9a385aa4ca3de188ca22562b0..0e1b222c0faed71701a8611a47a01fc3a900be7b 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 84fdb7d6d07dd5988aee7dc882c270fc14e38d03..63693d9758fedbe3af16b8b973ac8b2d6120be30 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 baf6ee05fffdab2c34a3f82427dc4ce30f01d82b..84016614e2a83c9da0480caf0c44b896dcce50c2 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 afeeb2565f57b820c4cac1fc5c1768bad30b47b8..01e18c9248cbed012d1b6d43189fa6b750c46331 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 3eca064e3a2c31391424af184357c501ba7933a3..a0ccde35f84e33075d4c136d75cb815a5e72bc0d 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 bc42dec6af8cdbd23e17a6088cc92c162ef83f71..6089fd7286105873433bdafcbce5dbe8957e7a42 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 28e16963385420dc420bd5f983637b54069d2a86..fe3c1e507d9cec6949216719285f691f08696958 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 3bca96ba9800ed8ed3d85e8dc22362621a95b1fc..1cc878c1e63ad7c82f1c95d25e26133daf5c4e0d 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 29e7f8cb1e655453bbf793df71eb336627a90981..12945928900478eefd54ef7dba987b86578bc722 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 c953d10f052f83db79c0137505799caeb771c2b5..b995b7e7da00b9eae2d0aa7f6a22c1fa83887171 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