From 28680ea2738d94b938b1e6a9357c55853dca7df2 Mon Sep 17 00:00:00 2001 From: chrfranke <chrfranke@4ea69e1a-61f1-4043-bf83-b5c94c648137> Date: Sat, 19 Dec 2009 15:25:27 +0000 Subject: [PATCH] Add '-v ID,FORMAT:BYTEORDER[,NAME]' to specify byte order of attribute raw value. git-svn-id: https://smartmontools.svn.sourceforge.net/svnroot/smartmontools/trunk@3001 4ea69e1a-61f1-4043-bf83-b5c94c648137 --- smartmontools/CHANGELOG | 3 ++ smartmontools/NEWS | 1 + smartmontools/atacmds.cpp | 80 ++++++++++++++++++++++------------ smartmontools/atacmds.h | 8 ++-- smartmontools/ataprint.cpp | 14 +++--- smartmontools/smartctl.8.in | 22 +++++++--- smartmontools/smartd.8.in | 6 +-- smartmontools/smartd.conf.5.in | 6 +-- 8 files changed, 93 insertions(+), 47 deletions(-) diff --git a/smartmontools/CHANGELOG b/smartmontools/CHANGELOG index 26a7c3849..1797f7256 100644 --- a/smartmontools/CHANGELOG +++ b/smartmontools/CHANGELOG @@ -43,6 +43,9 @@ NOTES FOR FUTURE RELEASES: see TODO file. <DEVELOPERS: ADDITIONS TO THE CHANGE LOG GO JUST BELOW HERE, PLEASE> + [CF] Add '-v ID,FORMAT:BYTEORDER[,NAME]' to specify byte order + of attribute raw value. + [CF] configure.in: Change --with-docdir default from 'PREFIX/share/doc/smartmontools-VERSION' to 'DATADIR/doc/smartmontools' to make it consistent with diff --git a/smartmontools/NEWS b/smartmontools/NEWS index 1474c6c78..9b04f65dc 100644 --- a/smartmontools/NEWS +++ b/smartmontools/NEWS @@ -8,6 +8,7 @@ http://smartmontools.svn.sourceforge.net/viewvc/smartmontools/trunk/smartmontool Date <Not released yet, please try current SVN> Summary: smartmontools release 5.40 ----------------------------------------------------------- +- Option '-v' allows to specify byte order of attribute raw value - configure: New default value for '--with-docdir'. - Drive database is in a separate source file 'drivedb.h' which can be downloaded from SVN. diff --git a/smartmontools/atacmds.cpp b/smartmontools/atacmds.cpp index c218cf0a2..6dc02ebf4 100644 --- a/smartmontools/atacmds.cpp +++ b/smartmontools/atacmds.cpp @@ -271,6 +271,19 @@ bool parse_attribute_def(const char * opt, ata_vendor_attr_defs & defs, flags = ATTRFLAG_INCREASING; } + // Split "format[:byteorder]" + char byteorder[8+1] = ""; + if (strchr(fmtname, ':')) { + if (!( sscanf(fmtname, "%*[^:]%n:%8[012345rvwz]%n", &n1, byteorder, &n2) >= 1 + && n2 == (int)strlen(fmtname))) + return false; + fmtname[n1] = 0; + if (strchr(byteorder, 'v')) + flags |= (ATTRFLAG_NO_NORMVAL|ATTRFLAG_NO_WORSTVAL); + if (strchr(byteorder, 'w')) + flags |= ATTRFLAG_NO_WORSTVAL; + } + // Find format name for (i = 0; ; i++) { if (i >= num_format_names) @@ -280,9 +293,9 @@ bool parse_attribute_def(const char * opt, ata_vendor_attr_defs & defs, } ata_attr_raw_format format = format_names[i].format; - // 64-bit formats use the normalized value bytes. - if (format == RAWFMT_RAW64 || format == RAWFMT_HEX64) - flags |= ATTRFLAG_NO_NORMVAL; + // 64-bit formats use the normalized and worst value bytes. + if (!*byteorder && (format == RAWFMT_RAW64 || format == RAWFMT_HEX64)) + flags |= (ATTRFLAG_NO_NORMVAL|ATTRFLAG_NO_WORSTVAL); if (!id) { // "N,format" -> set format for all entries @@ -294,6 +307,7 @@ bool parse_attribute_def(const char * opt, ata_vendor_attr_defs & defs, defs[i].priority = priority; defs[i].raw_format = format; defs[i].flags = flags; + strcpy(defs[i].byteorder, byteorder); } } else if (defs[id].priority <= priority) { @@ -303,6 +317,7 @@ bool parse_attribute_def(const char * opt, ata_vendor_attr_defs & defs, defs[id].raw_format = format; defs[id].priority = priority; defs[id].flags = flags; + strcpy(defs[id].byteorder, byteorder); } return true; @@ -317,7 +332,7 @@ std::string create_vendor_attribute_arg_list() std::string s; unsigned i; for (i = 0; i < num_format_names; i++) - s += strprintf("%s\tN,%s[,ATTR_NAME]", + s += strprintf("%s\tN,%s[:012345rvwz][,ATTR_NAME]", (i>0 ? "\n" : ""), format_names[i].name); for (i = 0; i < num_old_vendor_opts; i++) s += strprintf("\n\t%s", map_old_vendor_opts[i][0]); @@ -1736,8 +1751,8 @@ ata_attr_state ata_get_attr_state(const ata_smart_attribute & attr, if (attr.current <= thre.threshold) return ATTRSTATE_FAILED_NOW; - // Failed in the passed if worst value is below threshold - if (attr.worst <= thre.threshold) + // Failed in the past if worst value is below threshold + if (!(defs[attr.id].flags & ATTRFLAG_NO_WORSTVAL) && attr.worst <= thre.threshold) return ATTRSTATE_FAILED_PAST; return ATTRSTATE_OK; @@ -1767,24 +1782,36 @@ static ata_attr_raw_format get_default_raw_format(unsigned char id) uint64_t ata_get_attr_raw_value(const ata_smart_attribute & attr, const ata_vendor_attr_defs & defs) { - // Get 48 bit raw value - const unsigned char * raw = attr.raw; - uint64_t rawvalue; - rawvalue = raw[0] - | ( raw[1] << 8) - | ( raw[2] << 16) - | ((uint64_t)raw[3] << 24) - | ((uint64_t)raw[4] << 32) - | ((uint64_t)raw[5] << 40); - - if (defs[attr.id].flags & ATTRFLAG_NO_NORMVAL) { - // Some SSD vendors use bytes 3-10 from the Attribute - // Data Structure to store a 64-bit raw value. - rawvalue <<= 8; - rawvalue |= attr.worst; - rawvalue <<= 8; - rawvalue |= attr.current; + const ata_vendor_attr_defs::entry & def = defs[attr.id]; + + // Use default byteorder if not specified + const char * byteorder = def.byteorder; + if (!*byteorder) { + if (def.raw_format == RAWFMT_RAW64 || def.raw_format == RAWFMT_HEX64) + byteorder = "543210wv"; + else + byteorder = "543210"; + } + + // Build 64-bit value from selected bytes + uint64_t rawvalue = 0; + for (int i = 0; byteorder[i]; i++) { + unsigned char b; + switch (byteorder[i]) { + case '0': b = attr.raw[0]; break; + case '1': b = attr.raw[1]; break; + case '2': b = attr.raw[2]; break; + case '3': b = attr.raw[3]; break; + case '4': b = attr.raw[4]; break; + case '5': b = attr.raw[5]; break; + case 'r': b = attr.reserv; break; + case 'v': b = attr.current; break; + case 'w': b = attr.worst; break; + default : b = 0; break; + } + rawvalue <<= 8; rawvalue |= b; } + return rawvalue; } @@ -1793,7 +1820,7 @@ uint64_t ata_get_attr_raw_value(const ata_smart_attribute & attr, std::string ata_format_attr_raw_value(const ata_smart_attribute & attr, const ata_vendor_attr_defs & defs) { - // Get 48 bit or64 bit raw value + // Get 48 bit or 64 bit raw value uint64_t rawvalue = ata_get_attr_raw_value(attr, defs); // Get 16 bit words @@ -1821,6 +1848,7 @@ std::string ata_format_attr_raw_value(const ata_smart_attribute & attr, break; case RAWFMT_RAW48: + case RAWFMT_RAW64: s = strprintf("%"PRIu64, rawvalue); break; @@ -1828,10 +1856,6 @@ std::string ata_format_attr_raw_value(const ata_smart_attribute & attr, s = strprintf("0x%012"PRIx64, rawvalue); break; - case RAWFMT_RAW64: - s = strprintf("%"PRIu64, rawvalue); - break; - case RAWFMT_HEX64: s = strprintf("0x%016"PRIx64, rawvalue); break; diff --git a/smartmontools/atacmds.h b/smartmontools/atacmds.h index 8d5279d35..f5b8becaa 100644 --- a/smartmontools/atacmds.h +++ b/smartmontools/atacmds.h @@ -656,8 +656,9 @@ enum ata_attr_raw_format // Attribute flags enum { - ATTRFLAG_INCREASING = 0x01, // Value not reset (for reallocated/pending counts) - ATTRFLAG_NO_NORMVAL = 0x02 // Normalized value not valid + ATTRFLAG_INCREASING = 0x01, // Value not reset (for reallocated/pending counts) + ATTRFLAG_NO_NORMVAL = 0x02, // Normalized value not valid + ATTRFLAG_NO_WORSTVAL = 0x04 // Worst value not valid }; // Vendor attribute display defs for all attribute ids @@ -670,12 +671,13 @@ public: ata_attr_raw_format raw_format; // Raw value print format ata_vendor_def_prior priority; // Setting priority unsigned flags; // ATTRFLAG_* + char byteorder[8+1]; // String [012345rvwz] to define byte order entry() : raw_format(RAWFMT_DEFAULT), priority(PRIOR_DEFAULT), flags(0) - { } + { byteorder[0] = 0; } }; entry & operator[](unsigned char id) diff --git a/smartmontools/ataprint.cpp b/smartmontools/ataprint.cpp index 258c11f10..4bf3f6cfc 100644 --- a/smartmontools/ataprint.cpp +++ b/smartmontools/ataprint.cpp @@ -836,11 +836,15 @@ static void PrintSmartAttribWithThres(const ata_smart_values * data, } // Format value, worst, threshold - std::string valstr, threstr; + std::string valstr, worstr, threstr; if (state > ATTRSTATE_NO_NORMVAL) - valstr = strprintf("%.3d %.3d", attr.current, attr.worst); + valstr = strprintf("%.3d", attr.current); else - valstr = "--- ---"; + valstr = "---"; + if (!(defs[attr.id].flags & ATTRFLAG_NO_WORSTVAL)) + worstr = strprintf("%.3d", attr.worst); + else + worstr = "---"; if (state > ATTRSTATE_NO_THRESHOLD) threstr = strprintf("%.3d", thre.threshold); else @@ -848,9 +852,9 @@ static void PrintSmartAttribWithThres(const ata_smart_values * data, // Print line for each valid attribute std::string attrname = ata_get_smart_attr_name(attr.id, defs); - pout("%3d %-24s0x%04x %-9s %-3s %-10s%-9s%-12s%s\n", + pout("%3d %-24s0x%04x %-3s %-3s %-3s %-10s%-9s%-12s%s\n", attr.id, attrname.c_str(), attr.flags, - valstr.c_str(), threstr.c_str(), + valstr.c_str(), worstr.c_str(), threstr.c_str(), (ATTRIBUTE_FLAGS_PREFAILURE(attr.flags)? "Pre-fail" : "Old_age"), (ATTRIBUTE_FLAGS_ONLINE(attr.flags)? "Always" : "Offline"), (state == ATTRSTATE_FAILED_NOW ? "FAILING_NOW" : diff --git a/smartmontools/smartctl.8.in b/smartmontools/smartctl.8.in index 769217f64..fc814c5c7 100644 --- a/smartmontools/smartctl.8.in +++ b/smartmontools/smartctl.8.in @@ -1017,14 +1017,26 @@ writes a binary representation of the one sector log 0x11 (SATA Phy Event Counters) to file log.bin. .TP -.B \-v ID,FORMAT[,NAME], \-\-vendorattribute=ID,FORMAT[,NAME] -[ATA only] Sets a vendor\-specific raw value print FORMAT and -optional NAME for Attribute ID. +.B \-v ID,FORMAT[:BYTEORDER][,NAME], \-\-vendorattribute=ID,FORMAT[:BYTEORDER][,NAME] +[ATA only] Sets a vendor\-specific raw value print FORMAT, an optional +BYTEORDER and an optional NAME for Attribute ID. This option may be used multiple times. The Attribute ID can be in the range 1 to 255. If \'N\' is specified as -ID, the settings for all Attributes are changed. The NAME is a string of -letters, digits and underscore. +ID, the settings for all Attributes are changed. + +The optional BYTEORDER consists of 1 to 8 characters from the +set \'012345rvwz\'. The characters \'0\' to \'5\' select the byte 0 +to 5 from the 48\-bit raw value, \'r\' selects the reserved byte of +the attribute data block, \'v\' selects the normalized value, \'w\' +selects the worst value and \'z\' inserts a zero byte. +The default BYTEORDER is \'543210\' for all 48-bit formats, +and \'543210wv\' for the 64-bit formats. +For example, \'\-v 5,raw48:012345\' prints the raw value of +attribute 5 with big endian instead of little endian +byte ordering. + +The NAME is a string of letters, digits and underscore. .I \-v help \- Prints (to STDOUT) a list of all valid arguments to this option, diff --git a/smartmontools/smartd.8.in b/smartmontools/smartd.8.in index 177dd989c..619f45285 100644 --- a/smartmontools/smartd.8.in +++ b/smartmontools/smartd.8.in @@ -1605,9 +1605,9 @@ values for \'\-F\' (see the \'\-P\' option below). [Please see the \fBsmartctl \-F\fP command-line option.] .TP -.B \-v ID,FORMAT[,NAME] -[ATA only] Sets a vendor\-specific raw value print FORMAT and -optional NAME for Attribute ID. +.B \-v ID,FORMAT[:BYTEORDER][,NAME] +[ATA only] Sets a vendor\-specific raw value print FORMAT, an optional +BYTEORDER and an optional NAME for Attribute ID. This directive may be used multiple times. Please see \fBsmartctl -v\fP command-line option for further details. diff --git a/smartmontools/smartd.conf.5.in b/smartmontools/smartd.conf.5.in index 7038c7e1d..78c7e5d4c 100644 --- a/smartmontools/smartd.conf.5.in +++ b/smartmontools/smartd.conf.5.in @@ -1167,9 +1167,9 @@ values for \'\-F\' (see the \'\-P\' option below). [Please see the \fBsmartctl \-F\fP command-line option.] .TP -.B \-v ID,FORMAT[,NAME] -[ATA only] Sets a vendor\-specific raw value print FORMAT and -optional NAME for Attribute ID. +.B \-v ID,FORMAT[:BYTEORDER][,NAME] +[ATA only] Sets a vendor\-specific raw value print FORMAT, an optional +BYTEORDER and an optional NAME for Attribute ID. This directive may be used multiple times. Please see \fBsmartctl -v\fP command-line option for further details. -- GitLab