diff options
| author | Lennart Poettering <lennart@poettering.net> | 2009-03-19 01:10:43 +0100 | 
|---|---|---|
| committer | Lennart Poettering <lennart@poettering.net> | 2009-03-19 01:10:43 +0100 | 
| commit | 2735fd3198ffc5432b6fb807c4017deb35d401de (patch) | |
| tree | f5741a743c46a7fc2916c7b965aa247b365f67e8 | |
| parent | 70f4d5a5a95c61c64b12ac9c9ab5870bc96aec96 (diff) | |
add new API sk_disk_smart_get_overall()
| -rw-r--r-- | atasmart.c | 94 | ||||
| -rw-r--r-- | atasmart.h | 18 | 
2 files changed, 98 insertions, 14 deletions
@@ -1361,7 +1361,6 @@ const char* sk_smart_attribute_unit_to_string(SkSmartAttributeUnit unit) {          return _P(map[unit]);  } -  struct attr_helper {          uint64_t *value;          SkBool found; @@ -1386,7 +1385,6 @@ static void temperature_cb(SkDisk *d, const SkSmartAttributeParsedData *a, struc  int sk_disk_smart_get_temperature(SkDisk *d, uint64_t *kelvin) {          struct attr_helper ah; -        int r;          assert(d);          assert(kelvin); @@ -1394,8 +1392,8 @@ int sk_disk_smart_get_temperature(SkDisk *d, uint64_t *kelvin) {          ah.found = FALSE;          ah.value = kelvin; -        if ((r = sk_disk_smart_parse_attributes(d, (SkSmartAttributeParseCallback) temperature_cb, &ah)) < 0) -                return r; +        if (sk_disk_smart_parse_attributes(d, (SkSmartAttributeParseCallback) temperature_cb, &ah) < 0) +                return -1;          if (!ah.found) {                  errno = ENOENT; @@ -1424,7 +1422,6 @@ static void power_on_cb(SkDisk *d, const SkSmartAttributeParsedData *a, struct a  int sk_disk_smart_get_power_on(SkDisk *d, uint64_t *mseconds) {          struct attr_helper ah; -        int r;          assert(d);          assert(mseconds); @@ -1432,8 +1429,8 @@ int sk_disk_smart_get_power_on(SkDisk *d, uint64_t *mseconds) {          ah.found = FALSE;          ah.value = mseconds; -        if ((r = sk_disk_smart_parse_attributes(d, (SkSmartAttributeParseCallback) power_on_cb, &ah)) < 0) -                return r; +        if (sk_disk_smart_parse_attributes(d, (SkSmartAttributeParseCallback) power_on_cb, &ah) < 0) +                return -1;          if (!ah.found) {                  errno = ENOENT; @@ -1475,7 +1472,6 @@ static void pending_cb(SkDisk *d, const SkSmartAttributeParsedData *a, struct at  int sk_disk_smart_get_bad(SkDisk *d, uint64_t *sectors) {          struct attr_helper ah1, ah2;          uint64_t sectors1, sectors2; -        int r;          assert(d);          assert(sectors); @@ -1483,14 +1479,14 @@ int sk_disk_smart_get_bad(SkDisk *d, uint64_t *sectors) {          ah1.found = FALSE;          ah1.value = §ors1; -        if ((r = sk_disk_smart_parse_attributes(d, (SkSmartAttributeParseCallback) reallocated_cb, &ah1)) < 0) -                return r; +        if (sk_disk_smart_parse_attributes(d, (SkSmartAttributeParseCallback) reallocated_cb, &ah1) < 0) +                return -1;          ah2.found = FALSE;          ah2.value = §ors2; -        if ((r = sk_disk_smart_parse_attributes(d, (SkSmartAttributeParseCallback) pending_cb, &ah2)) < 0) -                return r; +        if (sk_disk_smart_parse_attributes(d, (SkSmartAttributeParseCallback) pending_cb, &ah2) < 0) +                return -1;          if (!ah1.found && !ah2.found) {                  errno = ENOENT; @@ -1507,6 +1503,64 @@ int sk_disk_smart_get_bad(SkDisk *d, uint64_t *sectors) {          return 0;  } +const char* sk_smart_overall_to_string(SkSmartOverall overall) { + +        /* %STRINGPOOLSTART% */ +        const char * const map[] = { +                [SK_SMART_OVERALL_GOOD] = "GOOD", +                [SK_SMART_OVERALL_BAD_STATUS] = "BAD_STATUS", +                [SK_SMART_OVERALL_BAD_ATTRIBUTE] = "BAD_ATTRIBUTE", +                [SK_SMART_OVERALL_BAD_SECTOR] = "BAD_SECTOR" +        }; +        /* %STRINGPOOLSTOP% */ + +        if (overall >= _SK_SMART_OVERALL_MAX) +                return NULL; + +        return _P(map[overall]); +} + +static void bad_attribute_cb(SkDisk *d, const SkSmartAttributeParsedData *a, SkBool *good) { +        if (a->good_valid && !a->good) +                *good = FALSE; +} + +int sk_disk_smart_get_overall(SkDisk *d, SkSmartOverall *overall) { +        SkBool good; +        uint64_t sectors; + +        assert(d); +        assert(overall); + +        if (sk_disk_smart_status(d, &good) < 0) +                return -1; + +        if (!good) { +                *overall = SK_SMART_OVERALL_BAD_STATUS; +                return 0; +        } + +        if (sk_disk_smart_get_bad(d, §ors) < 0) { +                if (errno != ENOENT) +                        return -1; +        } else if (sectors > 0) { +                *overall = SK_SMART_OVERALL_BAD_SECTOR; +                return 0; +        } + +        good = TRUE; +        if (sk_disk_smart_parse_attributes(d, (SkSmartAttributeParseCallback) bad_attribute_cb, &good) < 0) +                return -1; + +        if (!good) { +                *overall = SK_SMART_OVERALL_BAD_ATTRIBUTE; +                return 0; +        } + +        *overall = SK_SMART_OVERALL_GOOD; +        return 0; +} +  static char* print_name(char *s, size_t len, uint8_t id, const char *k) {          if (k) @@ -1649,6 +1703,7 @@ int sk_disk_dump(SkDisk *d) {                 ret >= 0 ? yes_no(awake) : "unknown");          if (disk_smart_is_available(d)) { +                SkSmartOverall overall;                  const SkSmartParsedData *spd;                  SkBool good;                  char pretty[32]; @@ -1657,7 +1712,7 @@ int sk_disk_dump(SkDisk *d) {                  if ((ret = sk_disk_smart_status(d, &good)) < 0)                          return ret; -                printf("Disk Health Good: %s\n", +                printf("SMART Disk Health Good: %s\n",                         yes_no(good));                  if ((ret = sk_disk_smart_read_data(d)) < 0) @@ -1692,7 +1747,10 @@ int sk_disk_dump(SkDisk *d) {                  if (sk_disk_smart_get_bad(d, &value) < 0)                          printf("Bad Sectors: %s\n", strerror(errno));                  else -                        printf("Bad Sectors: %s\n", print_value(pretty, sizeof(pretty), value, SK_SMART_ATTRIBUTE_UNIT_SECTORS)); +                        printf("%sBad Sectors: %s%s\n", +                               value > 0 ? HIGHLIGHT : "", +                               print_value(pretty, sizeof(pretty), value, SK_SMART_ATTRIBUTE_UNIT_SECTORS), +                               value > 0 ? ENDHIGHLIGHT : "");                  if (sk_disk_smart_get_power_on(d, &value) < 0)                          printf("Powered On: %s\n", strerror(errno)); @@ -1704,6 +1762,14 @@ int sk_disk_dump(SkDisk *d) {                  else                          printf("Temperature: %s\n", print_value(pretty, sizeof(pretty), value, SK_SMART_ATTRIBUTE_UNIT_MKELVIN)); +                if ((ret = sk_disk_smart_get_overall(d, &overall)) < 0) +                        return ret; + +                printf("%sOverall Status: %s%s\n", +                       overall != SK_SMART_OVERALL_GOOD ? HIGHLIGHT : "", +                       sk_smart_overall_to_string(overall), +                       overall != SK_SMART_OVERALL_GOOD ? ENDHIGHLIGHT : ""); +                  printf("%3s %-27s %5s %5s %5s %-11s %-14s %-7s %-7s %-3s\n",                         "ID#",                         "Name", @@ -25,6 +25,10 @@  #include <inttypes.h> +/* Please note that all enums defined here may be extended at any time + * without this being considered an ABI change. So take care when + * using them as indexes! */ +  #ifdef __cplusplus  extern "C" {  #endif @@ -149,6 +153,16 @@ typedef struct SkSmartAttributeParsedData {  typedef struct SkDisk SkDisk; +typedef enum SkSmartOverall  { +        SK_SMART_OVERALL_GOOD, +        SK_SMART_OVERALL_BAD_STATUS,     /* Smart Self Assessment negative */ +        SK_SMART_OVERALL_BAD_SECTOR,     /* At least one bad sector */ +        SK_SMART_OVERALL_BAD_ATTRIBUTE,  /* At least one attribute exceeded its threshold */ +        _SK_SMART_OVERALL_MAX +} SkSmartOverall; + +const char* sk_smart_overall_to_string(SkSmartOverall overall); +  int sk_disk_open(const char *name, SkDisk **d);  int sk_disk_get_size(SkDisk *d, uint64_t *bytes); @@ -162,6 +176,7 @@ typedef void (*SkSmartAttributeParseCallback)(SkDisk *d, const SkSmartAttributeP  int sk_disk_smart_is_available(SkDisk *d, SkBool *available);  int sk_disk_smart_status(SkDisk *d, SkBool *good); +  /* Reading SMART data might cause the disk to wake up from   * sleep. Hence from monitoring daemons make sure to call   * sk_disk_check_power_mode() to check wether the disk is sleeping and @@ -180,6 +195,9 @@ int sk_disk_smart_get_bad(SkDisk *d, uint64_t *sectors);  /* High level API to get the temperature */  int sk_disk_smart_get_temperature(SkDisk *d, uint64_t *kelvin); +/* Get overall status. This integrates the values of a couple of fields into a single overall status */ +int sk_disk_smart_get_overall(SkDisk *d, SkSmartOverall *overall); +  int sk_disk_dump(SkDisk *d);  void sk_disk_free(SkDisk *d);  | 
