+ state.temperature = currtemp;
+ }
+ else {
+ if (state.tempmin_delay) {
+ // End Min Temperature update delay if ...
+ if ( (state.tempmin && currtemp > state.tempmin) // current temp exceeds recorded min,
+ || (state.tempmin_delay <= time(0))) { // or delay time is over.
+ state.tempmin_delay = 0;
+ if (!state.tempmin)
+ state.tempmin = 255;
+ }
+ }
+
+ // Update Min Temperature
+ if (!state.tempmin_delay && currtemp < state.tempmin) {
+ state.tempmin = currtemp;
+ state.must_write = true;
+ if (currtemp != state.temperature)
+ minchg = "!";
+ }
+
+ // Track changes
+ if (cfg.tempdiff && (*minchg || *maxchg || abs((int)currtemp - (int)state.temperature) >= cfg.tempdiff)) {
+ PrintOut(LOG_INFO, "Device: %s, Temperature changed %+d Celsius to %u Celsius (Min/Max %s%s/%u%s)\n",
+ cfg.name.c_str(), (int)currtemp-(int)state.temperature, currtemp, fmt_temp(state.tempmin, buf), minchg, state.tempmax, maxchg);
+ state.temperature = currtemp;
+ }
+ }
+
+ // Check limits
+ if (cfg.tempcrit && currtemp >= cfg.tempcrit) {
+ PrintOut(LOG_CRIT, "Device: %s, Temperature %u Celsius reached critical limit of %u Celsius (Min/Max %s%s/%u%s)\n",
+ cfg.name.c_str(), currtemp, cfg.tempcrit, fmt_temp(state.tempmin, buf), minchg, state.tempmax, maxchg);
+ MailWarning(cfg, state, 12, "Device: %s, Temperature %d Celsius reached critical limit of %u Celsius (Min/Max %s%s/%u%s)",
+ cfg.name.c_str(), currtemp, cfg.tempcrit, fmt_temp(state.tempmin, buf), minchg, state.tempmax, maxchg);
+ }
+ else if (cfg.tempinfo && currtemp >= cfg.tempinfo) {
+ PrintOut(LOG_INFO, "Device: %s, Temperature %u Celsius reached limit of %u Celsius (Min/Max %s%s/%u%s)\n",
+ cfg.name.c_str(), currtemp, cfg.tempinfo, fmt_temp(state.tempmin, buf), minchg, state.tempmax, maxchg);
+ }
+ else if (cfg.tempcrit) {
+ unsigned char limit = (cfg.tempinfo ? cfg.tempinfo : cfg.tempcrit-5);
+ if (currtemp < limit)
+ reset_warning_mail(cfg, state, 12, "Temperature %u Celsius dropped below %u Celsius", currtemp, limit);
+ }
+}
+
+// Check normalized and raw attribute values.
+static void check_attribute(const dev_config & cfg, dev_state & state,
+ const ata_smart_attribute & attr,
+ const ata_smart_attribute & prev,
+ int attridx,
+ const ata_smart_threshold_entry * thresholds)
+{
+ // Check attribute and threshold
+ ata_attr_state attrstate = ata_get_attr_state(attr, attridx, thresholds, cfg.attribute_defs);
+ if (attrstate == ATTRSTATE_NON_EXISTING)
+ return;
+
+ // If requested, check for usage attributes that have failed.
+ if ( cfg.usagefailed && attrstate == ATTRSTATE_FAILED_NOW
+ && !cfg.monitor_attr_flags.is_set(attr.id, MONITOR_IGN_FAILUSE)) {
+ std::string attrname = ata_get_smart_attr_name(attr.id, cfg.attribute_defs, cfg.dev_rpm);
+ PrintOut(LOG_CRIT, "Device: %s, Failed SMART usage Attribute: %d %s.\n", cfg.name.c_str(), attr.id, attrname.c_str());
+ MailWarning(cfg, state, 2, "Device: %s, Failed SMART usage Attribute: %d %s.", cfg.name.c_str(), attr.id, attrname.c_str());
+ state.must_write = true;
+ }
+
+ // Return if we're not tracking this type of attribute
+ bool prefail = !!ATTRIBUTE_FLAGS_PREFAILURE(attr.flags);
+ if (!( ( prefail && cfg.prefail)
+ || (!prefail && cfg.usage )))
+ return;
+
+ // Return if '-I ID' was specified
+ if (cfg.monitor_attr_flags.is_set(attr.id, MONITOR_IGNORE))
+ return;
+
+ // Issue warning if they don't have the same ID in all structures.
+ if (attr.id != prev.id) {
+ PrintOut(LOG_INFO,"Device: %s, same Attribute has different ID numbers: %d = %d\n",
+ cfg.name.c_str(), attr.id, prev.id);
+ return;
+ }
+
+ // Compare normalized values if valid.
+ bool valchanged = false;
+ if (attrstate > ATTRSTATE_NO_NORMVAL) {
+ if (attr.current != prev.current)
+ valchanged = true;
+ }
+
+ // Compare raw values if requested.
+ bool rawchanged = false;
+ if (cfg.monitor_attr_flags.is_set(attr.id, MONITOR_RAW)) {
+ if ( ata_get_attr_raw_value(attr, cfg.attribute_defs)
+ != ata_get_attr_raw_value(prev, cfg.attribute_defs))
+ rawchanged = true;
+ }
+
+ // Return if no change
+ if (!(valchanged || rawchanged))
+ return;
+
+ // Format value strings
+ std::string currstr, prevstr;
+ if (attrstate == ATTRSTATE_NO_NORMVAL) {
+ // Print raw values only
+ currstr = strprintf("%s (Raw)",
+ ata_format_attr_raw_value(attr, cfg.attribute_defs).c_str());
+ prevstr = strprintf("%s (Raw)",
+ ata_format_attr_raw_value(prev, cfg.attribute_defs).c_str());
+ }
+ else if (cfg.monitor_attr_flags.is_set(attr.id, MONITOR_RAW_PRINT)) {
+ // Print normalized and raw values
+ currstr = strprintf("%d [Raw %s]", attr.current,
+ ata_format_attr_raw_value(attr, cfg.attribute_defs).c_str());
+ prevstr = strprintf("%d [Raw %s]", prev.current,
+ ata_format_attr_raw_value(prev, cfg.attribute_defs).c_str());