diff --git a/cmdline/mingw.c b/cmdline/mingw.c index fbf26ab0..02cd0565 100644 --- a/cmdline/mingw.c +++ b/cmdline/mingw.c @@ -1843,15 +1843,8 @@ static int devsmart(const char* file, uint64_t* smart, char* serial) { char cmd[128]; FILE* f; - int inside; - unsigned i; int ret; - *serial = 0; - for (i = 0; i < SMART_COUNT; ++i) - smart[i] = SMART_UNASSIGNED; - *serial = 0; - snprintf(cmd, sizeof(cmd), "smartctl-nc.exe -a %s", file); f = popen(cmd, "r"); @@ -1862,57 +1855,11 @@ static int devsmart(const char* file, uint64_t* smart, char* serial) /* LCOV_EXCL_STOP */ } - inside = 0; - while (1) { - char buf[256]; - char attr[64]; - unsigned id; - uint64_t raw; - char* s; - - s = fgets(buf, sizeof(buf), f); - - if (s == 0) - break; - - /* skip initial spaces */ - while (isspace(*s)) - ++s; - - if (*s == 0) { - inside = 0; - } else if (strncmp(s, "ID#", 3) == 0) { - inside = 1; - } else if (strncmp(s, "No Errors Logged", 16) == 0) { - smart[SMART_ERROR] = 0; - } else if (sscanf(s, "ATA Error Count: %" SCNu64, &raw) == 1) { - smart[SMART_ERROR] = raw; - } else if (sscanf(s, "Serial Number: %63s", serial) == 1) { - } else if (sscanf(s, "User Capacity: %63s", attr) == 1) { - smart[SMART_SIZE] = 0; - for (i = 0; attr[i]; ++i) { - if (isdigit(attr[i])) { - smart[SMART_SIZE] *= 10; - smart[SMART_SIZE] += attr[i] - '0'; - } - } - } else if (inside) { - if (sscanf(s, "%u %*s %*s %*u %*u %*u %*s %*s %*s %" SCNu64, &id, &raw) != 2) { - /* LCOV_EXCL_START */ - fprintf(stderr, "Invalid smartctl line '%s'.\n", buf); - return -1; - /* LCOV_EXCL_STOP */ - } - - if (id >= 256) { - /* LCOV_EXCL_START */ - fprintf(stderr, "Invalid SMART id '%u'.\n", id); - return -1; - /* LCOV_EXCL_STOP */ - } - - smart[id] = raw; - } + if (smartctl_attribute(f, smart, serial) != 0) { + /* LCOV_EXCL_START */ + pclose(f); + return -1; + /* LCOV_EXCL_STOP */ } ret = pclose(f); diff --git a/cmdline/support.c b/cmdline/support.c index 63b81672..6019d6db 100644 --- a/cmdline/support.c +++ b/cmdline/support.c @@ -394,4 +394,73 @@ char* strdup_nofail(const char* str) return ptr; } +/****************************************************************************/ +/* smartctl */ + +int smartctl_attribute(FILE* f, uint64_t* smart, char* serial) +{ + unsigned i; + int inside; + + /* preclear attribute */ + *serial = 0; + for (i = 0; i < SMART_COUNT; ++i) + smart[i] = SMART_UNASSIGNED; + + /* read the file */ + inside = 0; + while (1) { + char buf[256]; + char attr[64]; + unsigned id; + uint64_t raw; + char* s; + + s = fgets(buf, sizeof(buf), f); + + if (s == 0) + break; + + /* skip initial spaces */ + while (isspace(*s)) + ++s; + + if (*s == 0) { + inside = 0; + } else if (strncmp(s, "ID#", 3) == 0) { + inside = 1; + } else if (strncmp(s, "No Errors Logged", 16) == 0) { + smart[SMART_ERROR] = 0; + } else if (sscanf(s, "ATA Error Count: %" SCNu64, &raw) == 1) { + smart[SMART_ERROR] = raw; + } else if (sscanf(s, "Serial Number: %63s", serial) == 1) { + } else if (sscanf(s, "User Capacity: %63s", attr) == 1) { + smart[SMART_SIZE] = 0; + for (i = 0; attr[i]; ++i) { + if (isdigit(attr[i])) { + smart[SMART_SIZE] *= 10; + smart[SMART_SIZE] += attr[i] - '0'; + } + } + } else if (inside) { + if (sscanf(s, "%u %*s %*s %*u %*u %*u %*s %*s %*s %" SCNu64, &id, &raw) != 2) { + /* LCOV_EXCL_START */ + fprintf(stderr, "Invalid smartctl line '%s'.\n", buf); + return -1; + /* LCOV_EXCL_STOP */ + } + + if (id >= 256) { + /* LCOV_EXCL_START */ + fprintf(stderr, "Invalid SMART id '%u'.\n", id); + return -1; + /* LCOV_EXCL_STOP */ + } + + smart[id] = raw; + } + } + + return 0; +} diff --git a/cmdline/support.h b/cmdline/support.h index 99f82cce..f715c87f 100644 --- a/cmdline/support.h +++ b/cmdline/support.h @@ -121,5 +121,14 @@ char* strdup_nofail(const char* str); */ void malloc_fail(size_t size); +/****************************************************************************/ +/* smartctl */ + +/** + * Reads smartctl attributes from a stream. + * Returns -1 on error. + */ +int smartctl_attribute(FILE* f, uint64_t* smart, char* serial); + #endif diff --git a/cmdline/unix.c b/cmdline/unix.c index 93479e52..2d6e07fa 100644 --- a/cmdline/unix.c +++ b/cmdline/unix.c @@ -623,15 +623,8 @@ static int devsmart(dev_t device, uint64_t* smart, char* serial) { char cmd[128]; FILE* f; - int inside; - unsigned i; int ret; - *serial = 0; - for (i = 0; i < SMART_COUNT; ++i) - smart[i] = SMART_UNASSIGNED; - *serial = 0; - snprintf(cmd, sizeof(cmd), "smartctl -a /dev/block/%u:%u", major(device), minor(device)); f = popen(cmd, "r"); @@ -642,57 +635,11 @@ static int devsmart(dev_t device, uint64_t* smart, char* serial) /* LCOV_EXCL_STOP */ } - inside = 0; - while (1) { - char buf[256]; - char attr[64]; - unsigned id; - uint64_t raw; - char* s; - - s = fgets(buf, sizeof(buf), f); - - if (s == 0) - break; - - /* skip initial spaces */ - while (isspace(*s)) - ++s; - - if (*s == 0) { - inside = 0; - } else if (strncmp(s, "ID#", 3) == 0) { - inside = 1; - } else if (strncmp(s, "No Errors Logged", 16) == 0) { - smart[SMART_ERROR] = 0; - } else if (sscanf(s, "ATA Error Count: %" SCNu64, &raw) == 1) { - smart[SMART_ERROR] = raw; - } else if (sscanf(s, "Serial Number: %63s", serial) == 1) { - } else if (sscanf(s, "User Capacity: %63s", attr) == 1) { - smart[SMART_SIZE] = 0; - for (i = 0; attr[i]; ++i) { - if (isdigit(attr[i])) { - smart[SMART_SIZE] *= 10; - smart[SMART_SIZE] += attr[i] - '0'; - } - } - } else if (inside) { - if (sscanf(s, "%u %*s %*s %*u %*u %*u %*s %*s %*s %" SCNu64, &id, &raw) != 2) { - /* LCOV_EXCL_START */ - fprintf(stderr, "Invalid smartctl line '%s'.\n", buf); - return -1; - /* LCOV_EXCL_STOP */ - } - - if (id >= 256) { - /* LCOV_EXCL_START */ - fprintf(stderr, "Invalid SMART id '%u'.\n", id); - return -1; - /* LCOV_EXCL_STOP */ - } - - smart[id] = raw; - } + if (smartctl_attribute(f, smart, serial) != 0) { + /* LCOV_EXCL_START */ + pclose(f); + return -1; + /* LCOV_EXCL_STOP */ } ret = pclose(f);