return _P(map[unit]);
}
-
struct attr_helper {
uint64_t *value;
SkBool found;
int sk_disk_smart_get_temperature(SkDisk *d, uint64_t *kelvin) {
struct attr_helper ah;
- int r;
assert(d);
assert(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;
int sk_disk_smart_get_power_on(SkDisk *d, uint64_t *mseconds) {
struct attr_helper ah;
- int r;
assert(d);
assert(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;
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);
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;
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)
ret >= 0 ? yes_no(awake) : "unknown");
if (disk_smart_is_available(d)) {
+ SkSmartOverall overall;
const SkSmartParsedData *spd;
SkBool good;
char pretty[32];
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)
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));
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",
#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
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);
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
/* 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);