-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsmartcvt.cc
150 lines (119 loc) · 3.42 KB
/
smartcvt.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// converts smartctl output for nvme disks into old format
// purpose: input for munin smart_ plugin
// (c) 2021, 2024 A. Raphael
// License: free
// Warranty: none
#include <stdio.h>
#include <cstring>
#include <stdlib.h>
int getline2 ( char* buf, int max, FILE* inf );
char* replacews( char* desc );
long strtolx ( const char* p );
int main (int argc, char* argv[])
{
char log[1000];
int l;
int value;
double dvalue;
char *pT;
FILE *cmd;
/* Does not work on some drives:
// overwriting all arguments passed by plugin, except drive
char smartarg[100] = "smartctl -A ";
strcat( smartarg, argv[ argc-1 ] );
*/
// fix by mgc8:
// reconstruct all arguments passed by plugin
const int MAXARG = 100;
char smartarg[MAXARG] = "smartctl";
for ( int i = 1; i < argc; i++ ) {
strncat( smartarg, " ", MAXARG - strlen(smartarg) - 1 );
strncat( smartarg, argv[i], MAXARG - strlen(smartarg) - strlen(argv[i]) );
}
//
int on = 0;
int n = 0;
printf( "ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE\n" );
cmd = popen( smartarg, "r");
while ( ! feof( cmd ) )
{
l = getline2( log, 999, cmd);
// starting point of info-section
if ( strncmp("SMART/Health Information", log, 24) == 0 ) { on = 1; continue; }
// stop output at next blank line
if ( on && l <= 0 ) break;
if (on)
{
// Description may contain whitescpaces, but always ends with a colon
pT = strstr( log, ":" );
if ( ! pT ) continue;
// munin smart-plugin splits lines at whitespaces
// Therefore the description-field must NOT comtain spaces! Replace them with underscores
char* desc = replacews(log);
// Fetch smart-value
dvalue = strtolx(pT+1);
value = (int)dvalue;
// Squeeze all values into range 0-100
char prefixlevel = 0;
long multiplier = 1;
int exp = 0;
while ( dvalue > 100 ) { dvalue /= 10; multiplier *= 10; exp += 1; }
// output in old format
if ( multiplier > 1 )
{
if ( exp > 3 )
printf( "%i %s_(/1e%i) 0x0 %.2f %i 0 - - - %i\n", n+1, desc, exp, dvalue, (int)dvalue, value );
else
printf( "%i %s_(/%i) 0x0 %.2f %i 0 - - - %i\n", n+1, desc, (int)multiplier, dvalue, (int)dvalue, value );
}
else
printf( "%i %s 0x0 %.2f %i 0 - - - %i\n", n+1, desc, dvalue, (int)dvalue, value );
n++;
}
}
pclose(cmd);
return 0;
}
int getline2(char* buf, int max, FILE* inf)
{
int l;
*buf = 0;
fgets( buf, max, inf );
l = strlen(buf);
if ( l>0 && buf[l-1]=='\n' ) buf[--l] = 0;
while ( l>0 && buf[l-1]==' ' ) buf[--l] = 0;
return l;
}
// identifier must not comtain spaces! Replace them with underscores
char descbuf[256];
char* replacews( char* desc )
{
strncpy( descbuf, desc, 255 ); descbuf[255] = 0;
char* p = descbuf;
while ( *p )
{
if ( *p == ':' ) { *p = 0; break; }
if ( *p == ' ' || *p == '.' ) { *p = '_'; }
p++;
}
return descbuf;
}
// fetch smart value ( removing thousand-separators)
long strtolx( const char* p )
{
char buf[128];
char *dp = (char*)p;
int l=0;
// strip leading whitespaces
while (*dp==' ' || *dp=='\t') dp++;
// is hex value
if (dp[0]=='0' && dp[1]=='x') return strtol( dp, NULL, 16 );
// strip thousand-separators
while ( l<127 && *dp!=0 && strchr( "0123456789,", *dp )!=NULL )
{
if ( *dp != ',' ) buf[l++] = *dp;
dp++;
}
buf[l] = 0;
return atol(buf);
}