]> git.proxmox.com Git - mirror_smartmontools-debian.git/blob - knowndrives.cpp
Refreshed patches
[mirror_smartmontools-debian.git] / knowndrives.cpp
1 /*
2 * knowndrives.cpp
3 *
4 * Home page of code is: http://smartmontools.sourceforge.net
5 * Address of support mailing list: smartmontools-support@lists.sourceforge.net
6 *
7 * Copyright (C) 2003-9 Philip Williams, Bruce Allen
8 * Copyright (C) 2008-9 Christian Franke <smartmontools-support@lists.sourceforge.net>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
13 * any later version.
14 *
15 * You should have received a copy of the GNU General Public License
16 * (for example COPYING); if not, write to the Free
17 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 */
20
21 #include "config.h"
22 #include "int64.h"
23 #include <stdio.h>
24 #include "atacmds.h"
25 #include "extern.h"
26 #include "knowndrives.h"
27 #include "utility.h"
28
29 #ifdef HAVE_UNISTD_H
30 #include <unistd.h>
31 #endif
32 #ifdef _WIN32
33 #include <io.h> // access()
34 #endif
35
36 #include <stdexcept>
37
38 const char *knowndrives_c_cvsid="$Id: knowndrives.cpp 2986 2009-11-16 22:43:50Z manfred99 $"
39 ATACMDS_H_CVSID CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID KNOWNDRIVES_H_CVSID UTILITY_H_CVSID;
40
41 #define MODEL_STRING_LENGTH 40
42 #define FIRMWARE_STRING_LENGTH 8
43 #define TABLEPRINTWIDTH 19
44
45
46 /* Table of settings for known drives terminated by an element containing all
47 * zeros. The drivesettings structure is described in knowndrives.h. Note
48 * that lookupdrive() will search knowndrives[] from the start to end or
49 * until it finds the first match, so the order in knowndrives[] is important
50 * for distinct entries that could match the same drive. */
51
52 // Note that the table just below uses EXTENDED REGULAR EXPRESSIONS.
53 // A good on-line reference for these is:
54 // http://www.zeus.com/extra/docsystem/docroot/apps/web/docs/modules/access/regex.html
55
56 // Starting with CVS version 1.179 of this file, the regular expressions
57 // for drive model and firmware must match the full string. The effect of
58 // "^FULLSTRING$" is identical to "FULLSTRING". The special characters '^'
59 // and '$' are no longer required, but still allowed. The form ".*SUBSTRING.*"
60 // can be used if substring match is desired.
61
62 static const drive_settings builtin_knowndrives[] = {
63 // BEGIN drivedb.h (DO NOT DELETE - used by Makefile)
64 { "Apple SSD SM128",
65 "APPLE SSD SM128",
66 "", "", ""
67 },
68 { "Asus-Phison SSD",
69 "ASUS-PHISON SSD",
70 "", "", ""
71 },
72 { "OCZ Vertex SSD",
73 "OCZ[ -]VERTEX.*",
74 "", "",
75 " -v 9,raw64"
76 " -v 12,raw64"
77 " -v 184,raw64,Initial_Bad_Block_Count"
78 " -v 195,raw64,Program_Failure_Blk_Ct"
79 " -v 196,raw64,Erase_Failure_Blk_Ct"
80 " -v 197,raw64,Read_Failure_Blk_Ct"
81 " -v 198,raw64,Read_Sectors_Tot_Ct"
82 " -v 199,raw64,Write_Sectors_Tot_Ct"
83 " -v 200,raw64,Read_Commands_Tot_Ct"
84 " -v 201,raw64,Write_Commands_Tot_Ct"
85 " -v 202,raw64,Error_Bits_Flash_Tot_Ct"
86 " -v 203,raw64,Corr_Read_Errors_Tot_Ct"
87 " -v 204,raw64,Bad_Block_Full_Flag"
88 " -v 205,raw64,Max_PE_Count_Spec"
89 " -v 206,raw64,Min_Erase_Count"
90 " -v 207,raw64,Max_Erase_Count"
91 " -v 208,raw64,Average_Erase_Count"
92 " -v 209,raw64,Remaining_Lifetime_Perc"
93 },
94 { "OCZ Agility SSD",
95 "OCZ[ -]AGILITY",
96 "", "",
97 " -v 9,raw64"
98 " -v 12,raw64"
99 " -v 184,raw64,Initial_Bad_Block_Count"
100 " -v 195,raw64,Program_Failure_Blk_Ct"
101 " -v 196,raw64,Erase_Failure_Blk_Ct"
102 " -v 197,raw64,Read_Failure_Blk_Ct"
103 " -v 198,raw64,Read_Sectors_Tot_Ct"
104 " -v 199,raw64,Write_Sectors_Tot_Ct"
105 " -v 200,raw64,Read_Commands_Tot_Ct"
106 " -v 201,raw64,Write_Commands_Tot_Ct"
107 " -v 202,raw64,Error_Bits_Flash_Tot_Ct"
108 " -v 203,raw64,Corr_Read_Errors_Tot_Ct"
109 " -v 204,raw64,Bad_Block_Full_Flag"
110 " -v 205,raw64,Max_PE_Count_Spec"
111 " -v 206,raw64,Min_Erase_Count"
112 " -v 207,raw64,Max_Erase_Count"
113 " -v 208,raw64,Average_Erase_Count"
114 " -v 209,raw64,Remaining_Lifetime_Perc"
115 },
116 { "Intel X25-E SSD",
117 "SSDSA2SH(032|064)G1.* INTEL",
118 "", "",
119 "-v 225,raw48,Host_Writes_Count"
120 },
121 { "Transcend Solid-State Drive",
122 "TS(8|16|32|64|128)GSSD25-(M|S)",
123 "", "", ""
124 },
125 { "Transcend Solid-State Drive V series",
126 "TS(8|16|32|64|128|192)GSSD25S-(M|S)",
127 "", "", ""
128 },
129 { "Marvell SSD SD88SA024BA0 (SUN branded)",
130 "MARVELL SD88SA024BA0 SUN24G 0902M0054V",
131 "", "", ""
132 },
133 { "HP 1TB SATA disk GB1000EAFJL",
134 "GB1000EAFJL",
135 "", "", ""
136 },
137 { "IBM Deskstar 60GXP series", // ER60A46A firmware
138 "(IBM-|Hitachi )?IC35L0[12346]0AVER07.*",
139 "ER60A46A",
140 "", ""
141 },
142 { "IBM Deskstar 60GXP series", // All other firmware
143 "(IBM-|Hitachi )?IC35L0[12346]0AVER07.*",
144 "",
145 "IBM Deskstar 60GXP drives may need upgraded SMART firmware.\n"
146 "Please see http://www.geocities.com/dtla_update/index.html#rel and\n"
147 "http://www.ibm.com/pc/support/site.wss/MIGR-42215.html",
148 ""
149 },
150 { "IBM Deskstar 40GV & 75GXP series (A5AA/A6AA firmware)",
151 "(IBM-)?DTLA-30[57]0[123467][05].*",
152 "T[WX][123468AG][OF]A[56]AA",
153 "", ""
154 },
155 { "IBM Deskstar 40GV & 75GXP series (all other firmware)",
156 "(IBM-)?DTLA-30[57]0[123467][05].*",
157 "",
158 "IBM Deskstar 40GV and 75GXP drives may need upgraded SMART firmware.\n"
159 "Please see http://www.geocities.com/dtla_update/ and\n"
160 "http://www.ibm.com/pc/support/site.wss/MIGR-42215.html",
161 ""
162 },
163 { "", // ExcelStor J240, J340, J360, J680, and J880
164 "ExcelStor Technology J(24|34|36|68|88)0",
165 "", "", ""
166 },
167 { "", // Fujitsu M1623TAU
168 "FUJITSU M1623TAU",
169 "",
170 "",
171 "-v 9,seconds"
172 },
173 { "Fujitsu MHG series",
174 "FUJITSU MHG2...ATU?.*",
175 "",
176 "",
177 "-v 9,seconds"
178 },
179 { "Fujitsu MHH series",
180 "FUJITSU MHH2...ATU?.*",
181 "",
182 "",
183 "-v 9,seconds"
184 },
185 { "Fujitsu MHJ series",
186 "FUJITSU MHJ2...ATU?.*",
187 "",
188 "",
189 "-v 9,seconds"
190 },
191 { "Fujitsu MHK series",
192 "FUJITSU MHK2...ATU?.*",
193 "",
194 "",
195 "-v 9,seconds"
196 },
197 { "", // Fujitsu MHL2300AT
198 "FUJITSU MHL2300AT",
199 "",
200 "This drive's firmware has a harmless Drive Identity Structure\n"
201 "checksum error bug.",
202 "-v 9,seconds"
203 },
204 { "", // MHM2200AT, MHM2150AT, MHM2100AT, MHM2060AT
205 "FUJITSU MHM2(20|15|10|06)0AT",
206 "",
207 "This drive's firmware has a harmless Drive Identity Structure\n"
208 "checksum error bug.",
209 "-v 9,seconds"
210 },
211 { "Fujitsu MHN series",
212 "FUJITSU MHN2...AT",
213 "",
214 "",
215 "-v 9,seconds"
216 },
217 { "", // Fujitsu MHR2020AT
218 "FUJITSU MHR2020AT",
219 "",
220 "",
221 "-v 9,seconds"
222 },
223 { "", // Fujitsu MHR2040AT
224 "FUJITSU MHR2040AT",
225 "", // Tested on 40BA
226 "",
227 "-v 9,seconds -v 192,emergencyretractcyclect "
228 "-v 198,offlinescanuncsectorct -v 200,writeerrorcount"
229 },
230 { "Fujitsu MHSxxxxAT family",
231 "FUJITSU MHS20[6432]0AT( .)?",
232 "",
233 "",
234 "-v 9,seconds -v 192,emergencyretractcyclect "
235 "-v 198,offlinescanuncsectorct -v 200,writeerrorcount "
236 "-v 201,detectedtacount"
237 },
238 { "Fujitsu MHT series",
239 "FUJITSU MHT2...(AH|AS|AT|BH)U?.*",
240 "",
241 "",
242 "-v 9,seconds"
243 },
244 { "Fujitsu MHU series",
245 "FUJITSU MHU2...ATU?.*",
246 "",
247 "",
248 "-v 9,seconds"
249 },
250 { "Fujitsu MHV series",
251 "FUJITSU MHV2...(AH|AS|AT|BH|BS|BT).*",
252 "",
253 "",
254 "-v 9,seconds"
255 },
256 { "Fujitsu MPA..MPG series",
257 "FUJITSU MP[A-G]3...A[HTEV]U?.*",
258 "",
259 "",
260 "-v 9,seconds"
261 },
262 { "Fujitsu MHY2 BH series",
263 "FUJITSU MHY2(04|06|08|10|12|16|20|25)0BH.*",
264 "", "",
265 "-v 240,raw48,Transfer_Error_Rate"
266 },
267 { "Fujitsu MHW2 BH series",
268 "FUJITSU MHW2(04|06|08|10|12|16)0BH.*",
269 "", "", ""
270 },
271 { "Fujitsu MHW2 BJ series",
272 "FUJITSU MHW2(08|12|16)0BJ.*",
273 "", "", ""
274 },
275 { "Fujitsu MHZ2 BH series",
276 "FUJITSU MHZ2(04|08|12|16|20|25|32)0BH.*",
277 "", "", ""
278 },
279 { "Fujitsu MHZ2 BJ series",
280 "FUJITSU MHZ2(08|12|16|20|25|32)0BJ.*",
281 "",
282 "",
283 "-v 9,minutes"
284 },
285 { "Fujitsu MHZ2 BS series",
286 "FUJITSU MHZ2(12|25)0BS.*",
287 "", "", ""
288 },
289 { "", // Samsung SV4012H (known firmware)
290 "SAMSUNG SV4012H",
291 "RM100-08",
292 "",
293 "-v 9,halfminutes -F samsung"
294 },
295 { "", // Samsung SV4012H (all other firmware)
296 "SAMSUNG SV4012H",
297 "",
298 "May need -F samsung disabled; see manual for details.",
299 "-v 9,halfminutes -F samsung"
300 },
301 { "", // Samsung SV0412H (known firmware)
302 "SAMSUNG SV0412H",
303 "SK100-01",
304 "",
305 "-v 9,halfminutes -v 194,10xCelsius -F samsung"
306 },
307 { "", // Samsung SV0412H (all other firmware)
308 "SAMSUNG SV0412H",
309 "",
310 "May need -F samsung disabled; see manual for details.",
311 "-v 9,halfminutes -v 194,10xCelsius -F samsung"
312 },
313 { "", // Samsung SV1204H (known firmware)
314 "SAMSUNG SV1204H",
315 "RK100-1[3-5]",
316 "",
317 "-v 9,halfminutes -v 194,10xCelsius -F samsung"
318 },
319 { "", // Samsung SV1204H (all other firmware)
320 "SAMSUNG SV1204H",
321 "",
322 "May need -F samsung disabled; see manual for details.",
323 "-v 9,halfminutes -v 194,10xCelsius -F samsung"
324 },
325 { "", // SAMSUNG SV0322A tested with FW JK200-35
326 "SAMSUNG SV0322A",
327 "", "", ""
328 },
329 { "", // SAMSUNG SP40A2H with RR100-07 firmware
330 "SAMSUNG SP40A2H",
331 "RR100-07",
332 "",
333 "-v 9,halfminutes -F samsung"
334 },
335 { "", // SAMSUNG SP80A4H with RT100-06 firmware
336 "SAMSUNG SP80A4H",
337 "RT100-06",
338 "",
339 "-v 9,halfminutes -F samsung"
340 },
341 { "", // SAMSUNG SP8004H with QW100-61 firmware
342 "SAMSUNG SP8004H",
343 "QW100-61",
344 "",
345 "-v 9,halfminutes -F samsung"
346 },
347 { "SAMSUNG SpinPoint F1 DT series", // tested with HD103UJ/1AA01113
348 "SAMSUNG HD(083G|16[12]G|25[12]H|32[12]H|50[12]I|642J|75[23]L|10[23]U)J",
349 "", "", ""
350 },
351 { "SAMSUNG SpinPoint F1 RE series", // tested with HE103UJ/1AA01113
352 "SAMSUNG HE(252H|322H|502I|642J|753L|103U)J",
353 "", "", ""
354 },
355 { "SAMSUNG SpinPoint S250 series", // tested with HD200HJ/KF100-06
356 "SAMSUNG HD(162|200|250)HJ",
357 "", "", ""
358 },
359 { "SAMSUNG SpinPoint T133 series", // tested with HD300LJ/ZT100-12, HD400LJ/ZZ100-14, HD401LJ/ZZ100-15
360 "SAMSUNG HD(250KD|(30[01]|320|40[01])L[DJ])",
361 "", "", ""
362 },
363 { "SAMSUNG SpinPoint T166 series", // tested with HD501LJ/CR100-10
364 "SAMSUNG HD(080G|160H|32[01]K|403L|50[01]L)J",
365 "", "", ""
366 },
367 { "SAMSUNG SpinPoint P120 series", // VF100-37 firmware, tested with SP2514N/VF100-37
368 "SAMSUNG SP(16[01]3|2[05][01]4)[CN]",
369 "VF100-37",
370 "",
371 "-F samsung3"
372 },
373 { "SAMSUNG SpinPoint P120 series", // other firmware, tested with SP2504C/VT100-33
374 "SAMSUNG SP(16[01]3|2[05][01]4)[CN]",
375 "",
376 "May need -F samsung3 enabled; see manual for details.",
377 ""
378 },
379 { "SAMSUNG SpinPoint P80 SD series", // tested with HD160JJ/ZM100-33
380 "SAMSUNG HD(080H|120I|160J)J",
381 "", "", ""
382 },
383 { "SAMSUNG SpinPoint P80 series", // BH100-35 firmware, tested with SP0842N/BH100-35
384 "SAMSUNG SP(0451|08[0124]2|12[0145]3|16[0145]4)[CN]",
385 "BH100-35",
386 "",
387 "-F samsung3"
388 },
389 { "SAMSUNG SpinPoint P80 series", // firmware *-35 or later
390 "SAMSUNG SP(0451|08[0124]2|12[0145]3|16[0145]4)[CN]",
391 ".*-3[5-9]",
392 "May need -F samsung3 enabled; see manual for details.",
393 ""
394 },
395 { "SAMSUNG SpinPoint P80 series", // firmware *-25...34, tested with SP1614C/SW100-25 and -34
396 "SAMSUNG SP(0451|08[0124]2|12[0145]3|16[0145]4)[CN]",
397 ".*-(2[5-9]|3[0-4])",
398 "",
399 "-v 9,halfminutes -v 198,increasing"
400 },
401 { "SAMSUNG SpinPoint P80 series", // firmware *-23...24, tested with
402 // SP0802N/TK100-23,
403 // SP1213N/TL100-23,
404 // SP1604N/TM100-23 and -24
405 "SAMSUNG SP(0451|08[0124]2|12[0145]3|16[0145]4)[CN]",
406 ".*-2[34]",
407 "",
408 "-v 9,halfminutes -F samsung2"
409 },
410 { "SAMSUNG SpinPoint P80 series", // unknown firmware
411 "SAMSUNG SP(0451|08[0124]2|12[0145]3|16[0145]4)[CN]",
412 "",
413 "May need -F samsung2 or -F samsung3 enabled; see manual for details.",
414 ""
415 },
416 /*
417 // TODO: Make the entries below more specific.
418 // These entries produce misleading results, because newer
419 // Samsung disks reuse the version numbers *-NN.
420 { "", // All Samsung drives with '.*-25' firmware
421 "SAMSUNG.*",
422 ".*-25",
423 "May need -F samsung2 disabled; see manual for details.",
424 "-v 9,halfminutes -F samsung2"
425 },
426 { "", // All Samsung drives with '.*-26 or later (currently to -39)' firmware
427 "SAMSUNG.*",
428 ".*-(2[6789]|3[0-9])",
429 "",
430 "-v 9,halfminutes"
431 },
432 { "", // Samsung ALL OTHER DRIVES
433 "SAMSUNG.*",
434 "",
435 "May need -F samsung or -F samsung2 enabled; see manual for details.",
436 ""
437 },
438 */
439 { "Maxtor Fireball 541DX family",
440 "Maxtor 2B0(0[468]|1[05]|20)H1",
441 "",
442 "",
443 "-v 9,minutes -v 194,unknown"
444 },
445 { "Maxtor Fireball 3 family",
446 "Maxtor 2F0[234]0[JL]0",
447 "",
448 "",
449 "-v 9,minutes"
450 },
451 { "Maxtor DiamondMax 1280 ATA family", // no self-test log, ATA2-Fast
452 "Maxtor 8(1280A2|2160A4|2560A4|3840A6|4000A6|5120A8)",
453 "",
454 "",
455 "-v 9,minutes"
456 },
457 { "Maxtor DiamondMax 2160 Ultra ATA family",
458 "Maxtor 8(2160D2|3228D3|3240D3|4320D4|6480D6|8400D8|8455D8)",
459 "",
460 "",
461 "-v 9,minutes"
462 },
463 { "Maxtor DiamondMax 2880 Ultra ATA family",
464 "Maxtor 9(0510D4|0576D4|0648D5|0720D5|0840D6|0845D6|0864D6|1008D7|1080D8|1152D8)",
465 "",
466 "",
467 "-v 9,minutes"
468 },
469 { "Maxtor DiamondMax 3400 Ultra ATA family",
470 "Maxtor 9(1(360|350|202)D8|1190D7|10[12]0D6|0840D5|06[48]0D4|0510D3|1(350|202)E8|1010E6|0840E5|0640E4)",
471 "",
472 "",
473 "-v 9,minutes"
474 },
475 { "Maxtor DiamondMax D540X-4G family",
476 "Maxtor 4G(120J6|160J[68])",
477 "",
478 "",
479 "-v 9,minutes -v 194,unknown"
480 },
481 { "Maxtor DiamondMax D540X-4K family",
482 "MAXTOR 4K(020H1|040H2|060H3|080H4)",
483 "", "", ""
484 },
485 { "Maxtor DiamondMax Plus D740X family",
486 "MAXTOR 6L0(20[JL]1|40[JL]2|60[JL]3|80[JL]4)",
487 "", "", ""
488 },
489 { "Maxtor DiamondMax Plus 5120 Ultra ATA 33 family",
490 "Maxtor 9(0512D2|0680D3|0750D3|0913D4|1024D4|1360D6|1536D6|1792D7|2048D8)",
491 "",
492 "",
493 "-v 9,minutes"
494 },
495 { "Maxtor DiamondMax Plus 6800 Ultra ATA 66 family",
496 "Maxtor 9(2732U8|2390U7|204[09]U6|1707U5|1366U4|1024U3|0845U3|0683U2)",
497 "",
498 "",
499 "-v 9,minutes"
500 },
501 { "Maxtor DiamondMax D540X-4D",
502 "Maxtor 4D0(20H1|40H2|60H3|80H4)",
503 "",
504 "",
505 "-v 9,minutes -v 194,unknown"
506 },
507 { "Maxtor DiamondMax 16 family",
508 "Maxtor 4(R0[68]0[JL]0|R1[26]0L0|A160J0|R120L4)",
509 "",
510 "",
511 "-v 9,minutes"
512 },
513 { "Maxtor DiamondMax 4320 Ultra ATA family",
514 "Maxtor (91728D8|91512D7|91303D6|91080D5|90845D4|90645D3|90648D[34]|90432D2)",
515 "",
516 "",
517 "-v 9,minutes"
518 },
519 { "Maxtor DiamondMax 17 VL family",
520 "Maxtor 9(0431U1|0641U2|0871U2|1301U3|1741U4)",
521 "",
522 "",
523 "-v 9,minutes"
524 },
525 { "Maxtor DiamondMax 20 VL family",
526 "Maxtor (94091U8|93071U6|92561U5|92041U4|91731U4|91531U3|91361U3|91021U2|90841U2|90651U2)",
527 "",
528 "",
529 "-v 9,minutes"
530 },
531 { "Maxtor DiamondMax VL 30 family", // U: ATA66, H: ATA100
532 "Maxtor (33073U4|32049U3|31536U2|30768U1|33073H4|32305H3|31536H2|30768H1)",
533 "",
534 "",
535 "-v 9,minutes"
536 },
537 { "Maxtor DiamondMax 36 family",
538 "Maxtor (93652U8|92739U6|91826U4|91369U3|90913U2|90845U2|90435U1)",
539 "",
540 "",
541 "-v 9,minutes"
542 },
543 { "Maxtor DiamondMax 40 ATA 66 series",
544 "Maxtor 9(0684U2|1024U2|1362U3|1536U3|2049U4|2562U5|3073U6|4098U8)",
545 "",
546 "",
547 "-v 9,minutes"
548 },
549 { "Maxtor DiamondMax Plus 40 series (Ultra ATA 66 and Ultra ATA 100)",
550 "Maxtor (54098[UH]8|53073[UH]6|52732[UH]6|52049[UH]4|51536[UH]3|51369[UH]3|51024[UH]2)",
551 "",
552 "",
553 "-v 9,minutes"
554 },
555 { "Maxtor DiamondMax 40 VL Ultra ATA 100 series",
556 "Maxtor 3(1024H1|1535H2|2049H2|3073H3|4098H4)( B)?",
557 "",
558 "",
559 "-v 9,minutes"
560 },
561 { "Maxtor DiamondMax Plus 45 Ulta ATA 100 family",
562 "Maxtor 5(4610H6|4098H6|3073H4|2049H3|1536H2|1369H2|1023H2)",
563 "",
564 "",
565 "-v 9,minutes"
566 },
567 { "Maxtor DiamondMax 60 ATA 66 family",
568 "Maxtor 9(1023U2|1536U2|2049U3|2305U3|3073U4|4610U6|6147U8)",
569 "",
570 "",
571 "-v 9,minutes"
572 },
573 { "Maxtor DiamondMax 60 ATA 100 family",
574 "Maxtor 9(1023H2|1536H2|2049H3|2305H3|3073H4|4098H6|4610H6|6147H8)",
575 "",
576 "",
577 "-v 9,minutes"
578 },
579 { "Maxtor DiamondMax Plus 60 family",
580 "Maxtor 5T0(60H6|40H4|30H3|20H2|10H1)",
581 "",
582 "",
583 "-v 9,minutes"
584 },
585 { "Maxtor DiamondMax 80 family",
586 "Maxtor (98196H8|96147H6)",
587 "",
588 "",
589 "-v 9,minutes"
590 },
591 { "Maxtor DiamondMax 536DX family",
592 "Maxtor 4W(100H6|080H6|060H4|040H3|030H2)",
593 "",
594 "",
595 "-v 9,minutes"
596 },
597 { "Maxtor DiamondMax Plus 8 family",
598 "Maxtor 6(E0[234]|K04)0L0",
599 "",
600 "",
601 "-v 9,minutes"
602 },
603 { "Maxtor DiamondMax 10 family (ATA/133 and SATA/150)",
604 "Maxtor 6(B(30|25|20|16|12|10|08)0[MPRS]|L(080[MLP]|(100|120)[MP]|160[MP]|200[MPRS]|250[RS]|300[RS]))0",
605 "",
606 "",
607 "-v 9,minutes"
608 },
609 { "Maxtor DiamondMax 10 family (SATA/300)",
610 "Maxtor 6V(080E|160E|200E|250F|300F|320F)0",
611 "", "", ""
612 },
613 { "Maxtor DiamondMax Plus 9 family",
614 "Maxtor 6Y((060|080|120|160)L0|(060|080|120|160|200|250)P0|(060|080|120|160|200|250)M0)",
615 "",
616 "",
617 "-v 9,minutes"
618 },
619 { "Maxtor DiamondMax 11 family",
620 "Maxtor 6H[45]00[FR]0",
621 "", "", ""
622 },
623 { "Maxtor DiamondMax 17",
624 "Maxtor 6G(080L|160[PE])0",
625 "", "", ""
626 },
627 { "Seagate Maxtor DiamondMax 20",
628 "MAXTOR STM3(40|80|160)[28]1[12]0?AS?",
629 "", "", ""
630 },
631 { "Seagate Maxtor DiamondMax 21",
632 "MAXTOR STM3(160215|(250|320)820|320620|500630)AS?",
633 "", "", ""
634 },
635 { "Seagate Maxtor DiamondMax 22", // fixed firmware
636 "(MAXTOR )?STM3(500320|750330|1000340)AS?",
637 "MX1A", // http://seagate.custkb.com/seagate/crm/selfservice/search.jsp?DocId=207969
638 "", ""
639 },
640 { "Seagate Maxtor DiamondMax 22", // fixed firmware
641 "(MAXTOR )?STM3(160813|320614|640323|1000334)AS?",
642 "MX1B", // http://seagate.custkb.com/seagate/crm/selfservice/search.jsp?DocId=207975
643 "", ""
644 },
645 { "Seagate Maxtor DiamondMax 22", // buggy firmware
646 "(MAXTOR )?STM3(500320|750330|1000340)AS?",
647 "MX15",
648 "There are known problems with these drives,\n"
649 "AND THIS FIRMWARE VERSION IS AFFECTED,\n"
650 "see the following Seagate web pages:\n"
651 "http://seagate.custkb.com/seagate/crm/selfservice/search.jsp?DocId=207931\n"
652 "http://seagate.custkb.com/seagate/crm/selfservice/search.jsp?DocId=207969",
653 ""
654 },
655 { "Seagate Maxtor DiamondMax 22", // unknown firmware
656 "(MAXTOR )?STM3(160813|32061[34]|500320|640323|750330|10003(34|40))AS?",
657 "",
658 "There are known problems with these drives,\n"
659 "see the following Seagate web pages:\n"
660 "http://seagate.custkb.com/seagate/crm/selfservice/search.jsp?DocId=207931\n"
661 "http://seagate.custkb.com/seagate/crm/selfservice/search.jsp?DocId=207969\n"
662 "http://seagate.custkb.com/seagate/crm/selfservice/search.jsp?DocId=207975",
663 ""
664 },
665 { "Seagate Maxtor DiamondMax 23",
666 "STM3((160|250)31|(320|500)41|(750|1000)52)8AS?",
667 "", "", ""
668 },
669 { "Maxtor MaXLine Plus II",
670 "Maxtor 7Y250[PM]0",
671 "",
672 "",
673 "-v 9,minutes"
674 },
675 { "Maxtor MaXLine II family",
676 "Maxtor [45]A(25|30|32)0[JN]0",
677 "",
678 "",
679 "-v 9,minutes"
680 },
681 { "Maxtor MaXLine III family (ATA/133 and SATA/150)",
682 "Maxtor 7L(25|30)0[SR]0",
683 "",
684 "",
685 "-v 9,minutes"
686 },
687 { "Maxtor MaXLine III family (SATA/300)",
688 "Maxtor 7V(25|30)0F0",
689 "", "", ""
690 },
691 { "Maxtor MaXLine Pro 500 family", // There is also a 7H500R0 model, but I
692 "Maxtor 7H500F0", // haven't added it because I suspect
693 "", // it might need vendoropts_9_minutes
694 "", "" // and nobody has submitted a report yet
695 },
696 { "", // HITACHI_DK14FA-20B
697 "HITACHI_DK14FA-20B",
698 "",
699 "",
700 "-v 9,minutes -v 193,loadunload"
701 },
702 { "HITACHI Travelstar DK23XX/DK23XXB series",
703 "HITACHI_DK23..-..B?",
704 "",
705 "",
706 "-v 9,minutes -v 193,loadunload"
707 },
708 { "Hitachi Endurastar J4K20/N4K20 (formerly DK23FA-20J)",
709 "(HITACHI_DK23FA-20J|HTA422020F9AT[JN]0)",
710 "",
711 "",
712 "-v 9,minutes -v 193,loadunload"
713 },
714 { "Hitachi Endurastar J4K30/N4K30",
715 "HE[JN]4230[23]0F9AT00",
716 "",
717 "",
718 "-v 9,minutes -v 193,loadunload"
719 },
720 { "Hitachi Travelstar C4K60 family", // 1.8" slim drive
721 "HTC4260[23]0G5CE00|HTC4260[56]0G8CE00",
722 "",
723 "",
724 "-v 9,minutes -v 193,loadunload"
725 },
726 { "IBM Travelstar 4GT family",
727 "IBM-DTCA-2(324|409)0",
728 "", "", ""
729 },
730 { "IBM Travelstar 6GN family",
731 "IBM-DBCA-20(324|486|648)0",
732 "", "", ""
733 },
734 { "IBM Travelstar 25GS, 18GT, and 12GN family",
735 "IBM-DARA-2(25|18|15|12|09|06)000",
736 "", "", ""
737 },
738 { "IBM Travelstar 14GS",
739 "IBM-DCYA-214000",
740 "", "", ""
741 },
742 { "IBM Travelstar 4LP",
743 "IBM-DTNA-2(180|216)0",
744 "", "", ""
745 },
746 { "IBM Travelstar 48GH, 30GN, and 15GN family",
747 "(IBM-|Hitachi )?IC25(T048ATDA05|N0(30|20|15|12|10|07|06|05)ATDA04)-.",
748 "", "", ""
749 },
750 { "IBM Travelstar 32GH, 30GT, and 20GN family",
751 "IBM-DJSA-2(32|30|20|10|05)",
752 "", "", ""
753 },
754 { "IBM Travelstar 4GN family",
755 "IBM-DKLA-2(216|324|432)0",
756 "", "", ""
757 },
758 { "IBM/Hitachi Travelstar 60GH and 40GN family",
759 "(IBM-|Hitachi )?IC25(T060ATC[SX]05|N0[4321]0ATC[SX]04)-.",
760 "", "", ""
761 },
762 { "IBM/Hitachi Travelstar 40GNX family",
763 "(IBM-|Hitachi )?IC25N0[42]0ATC[SX]05-.",
764 "", "", ""
765 },
766 { "Hitachi Travelstar 80GN family",
767 "(Hitachi )?IC25N0[23468]0ATMR04-.",
768 "", "", ""
769 },
770 { "Hitachi Travelstar 4K40",
771 "(Hitachi )?HTS4240[234]0M9AT00",
772 "", "", ""
773 },
774 { "Hitachi Travelstar 4K120",
775 "(Hitachi )?(HTS4212(60|80|10|12)H9AT00|HTS421260G9AT00)",
776 "", "", ""
777 },
778 { "Hitachi Travelstar 5K80 family",
779 "(Hitachi )?HTS5480[8642]0M9AT00",
780 "", "", ""
781 },
782 { "Hitachi Travelstar 5K100 series",
783 "(Hitachi )?HTS5410[1864]0G9(AT|SA)00",
784 "", "", ""
785 },
786 { "Hitachi Travelstar E5K100 series",
787 "(Hitachi )?HTE541040G9(AT|SA)00",
788 "", "", ""
789 },
790 { "Hitachi Travelstar 5K120",
791 "(Hitachi )?HTS5412(60|80|10|12)H9(AT|SA)00",
792 "", "", ""
793 },
794 { "Hitachi Travelstar 5K160 series",
795 "(Hitachi |HITACHI )?HTS5416([468]0|1[26])J9(AT|SA)00",
796 "", "", ""
797 },
798 { "Hitachi Travelstar E5K160 series",
799 "(Hitachi )?HTE5416(12|16|60|80)J9(AT|SA)00",
800 "", "", ""
801 },
802 { "Hitachi Travelstar 5K250 series",
803 "(Hitachi |HITACHI )?HTS5425(80|12|16|20|25)K9(A3|SA)00",
804 "", "", ""
805 },
806 { "Hitachi Travelstar 5K320 series",
807 "(Hitachi |HITACHI )?HT(S|E)5432(80|12|16|25|32)L9(A300|SA01)",
808 "", "", ""
809 },
810 { "Hitachi Travelstar 7K60",
811 "(Hitachi )?HTS726060M9AT00",
812 "", "", ""
813 },
814 { "Hitachi Travelstar E7K60",
815 "(Hitachi )?HTE7260[46]0M9AT00",
816 "", "", ""
817 },
818 { "Hitachi Travelstar 7K100",
819 "(Hitachi )?HTS7210[168]0G9(AT|SA)00",
820 "", "", ""
821 },
822 { "Hitachi Travelstar E7K100",
823 "(Hitachi )?HTE7210[168]0G9(AT|SA)00",
824 "", "", ""
825 },
826 { "Hitachi Travelstar 7K200",
827 "(Hitachi )?HTS7220(80|10|12|16|20)K9(A3|SA)00",
828 "", "", ""
829 },
830 { "IBM Deskstar 14GXP and 16GP series",
831 "IBM-DTTA-3(7101|7129|7144|5032|5043|5064|5084|5101|5129|5168)0",
832 "", "", ""
833 },
834 { "IBM Deskstar 25GP and 22GXP family",
835 "IBM-DJNA-3(5(101|152|203|250)|7(091|135|180|220))0",
836 "", "", ""
837 },
838 { "IBM Deskstar 37GP and 34GXP family",
839 "IBM-DPTA-3(5(375|300|225|150)|7(342|273|205|136))0",
840 "", "", ""
841 },
842 { "IBM/Hitachi Deskstar 120GXP family",
843 "(IBM-)?IC35L((020|040|060|080|120)AVVA|0[24]0AVVN)07-[01]",
844 "", "", ""
845 },
846 { "IBM/Hitachi Deskstar GXP-180 family",
847 "(IBM-)?IC35L(030|060|090|120|180)AVV207-[01]",
848 "", "", ""
849 },
850 { "Hitachi Deskstar 7K80 series",
851 "(Hitachi )?HDS7280([48]0PLAT20|(40)?PLA320|80PLA380).*",
852 "", "", ""
853 },
854 { "Hitachi Deskstar 7K160",
855 "(Hitachi )?HDS7216(80|16)PLA[3T]80.*",
856 "", "", ""
857 },
858 { "Hitachi Deskstar 7K250 series",
859 "(Hitachi )?HDS7225((40|80|12|16)VLAT20|(12|16|25)VLAT80|(80|12|16|25)VLSA80)",
860 "", "", ""
861 },
862 { "Hitachi Deskstar 7K250 (SUN branded)",
863 "HITACHI HDS7225SBSUN250G.*",
864 "", "", ""
865 },
866 { "Hitachi Deskstar T7K250 series",
867 "(Hitachi )?HDT7225((25|20|16)DLA(T80|380))",
868 "", "", ""
869 },
870 { "Hitachi Deskstar 7K400 series",
871 "(Hitachi )?HDS724040KL(AT|SA)80",
872 "", "", ""
873 },
874 { "Hitachi Deskstar 7K500 series",
875 "(Hitachi )?HDS725050KLA(360|T80)",
876 "", "", ""
877 },
878 { "Hitachi Deskstar P7K500 series",
879 "(Hitachi )?HDP7250(16|25|32|40|50)GLA(36|38|T8)0",
880 "", "", ""
881 },
882 { "Hitachi Deskstar T7K500",
883 "(Hitachi )?HDT7250(25|32|40|50)VLA(360|380|T80)",
884 "", "", ""
885 },
886 { "Hitachi Deskstar 7K1000",
887 "(Hitachi )?HDS7210(50|75|10)KLA330",
888 "", "", ""
889 },
890 { "Hitachi Deskstar 7K1000.B",
891 "(Hitachi )?HDT7210((16|25)SLA380|(32|50|64|75|10)SLA360)",
892 "", "", ""
893 },
894 { "Hitachi Deskstar 7K2000",
895 "Hitachi HDS722020ALA330",
896 "", "", ""
897 },
898 { "Hitachi Ultrastar 7K1000",
899 "(Hitachi )?HUA7210(50|75|10)KLA330",
900 "", "", ""
901 },
902 { "Toshiba 2.5\" HDD series (10-20 GB)",
903 "TOSHIBA MK(101[67]GAP|15[67]GAP|20(1[678]GAP|(18|23)GAS))",
904 "", "", ""
905 },
906 { "Toshiba 2.5\" HDD series (30-60 GB)",
907 "TOSHIBA MK((6034|4032)GSX|(6034|4032)GAX|(6026|4026|4019|3019)GAXB?|(6025|6021|4025|4021|4018|3025|3021|3018)GAS|(4036|3029)GACE?|(4018|3017)GAP)",
908 "", "", ""
909 },
910 { "Toshiba 2.5\" HDD series (80 GB and above)",
911 "TOSHIBA MK(80(25GAS|26GAX|32GAX|32GSX)|10(31GAS|32GAX)|12(33GAS|34G[AS]X)|2035GSS)",
912 "", "", ""
913 },
914 { "Toshiba 2.5\" HDD MK..52GSX series",
915 "TOSHIBA MK(80|12|16|25|32)52GSX",
916 "", "", ""
917 },
918 { "Toshiba 1.8\" HDD series",
919 "TOSHIBA MK[23468]00[4-9]GA[HL]",
920 "", "", ""
921 },
922 { "", // TOSHIBA MK6022GAX
923 "TOSHIBA MK6022GAX",
924 "", "", ""
925 },
926 { "", // TOSHIBA MK6409MAV
927 "TOSHIBA MK6409MAV",
928 "", "", ""
929 },
930 { "Toshiba MKx019GAXB (SUN branded)",
931 "TOS MK[34]019GAXB SUN[34]0G",
932 "", "", ""
933 },
934 { "Seagate Momentus family",
935 "ST9(20|28|40|48)11A",
936 "", "", ""
937 },
938 { "Seagate Momentus 42 family",
939 "ST9(2014|3015|4019)A",
940 "", "", ""
941 },
942 { "Seagate Momentus 4200.2 series",
943 "ST9(100822|808210|60821|50212|402113|30219)A",
944 "", "", ""
945 },
946 { "Seagate Momentus 5400.2 series",
947 "ST9(808211|60822|408114|308110|120821|10082[34]|8823|6812|4813|3811)AS?",
948 "", "", ""
949 },
950 { "Seagate Momentus 5400.3 series",
951 "ST9(4081[45]|6081[35]|8081[15]|100828|120822|160821)AS?",
952 "", "", ""
953 },
954 { "Seagate Momentus 5400.3 ED series",
955 "ST9(4081[45]|6081[35]|8081[15]|100828|120822|160821)AB",
956 "", "", ""
957 },
958 { "Seagate Momentus 5400.4 series",
959 "ST9(120817|(160|200|250)827)AS",
960 "", "", ""
961 },
962 { "Seagate Momentus 5400.5 series",
963 "ST9((80|120|160)310|(250|320)320)AS",
964 "", "", ""
965 },
966 { "Seagate Momentus 5400.6 series",
967 "ST9((12|25)0315AS|500325)ASG?",
968 "", "", ""
969 },
970 { "Seagate Momentus 5400 PSD series", // Hybrid drives
971 "ST9(808212|(120|160)8220)AS",
972 "", "", ""
973 },
974 { "Seagate Momentus 7200.1 series",
975 "ST9(10021|80825|6023|4015)AS?",
976 "", "", ""
977 },
978 { "Seagate Momentus 7200.2 series",
979 "ST9(80813|100821|120823|160823|200420)ASG?",
980 "", "", ""
981 },
982 { "Seagate Momentus 7200.3 series",
983 "ST9((80|120|160)411|(250|320)421)ASG?",
984 "", "", ""
985 },
986 { "Seagate Momentus 7200.4 series",
987 "ST9(160412|250410|320423|500420)ASG?",
988 "", "", ""
989 },
990 { "Seagate Momentus 7200 FDE.2 series",
991 "ST9((160413|25041[12]|320426|50042[12])AS|(16041[89]|2504[16]4|32042[67]|500426)ASG)",
992 "", "", ""
993 },
994 { "Seagate Medalist 1010, 1721, 2120, 3230 and 4340", // ATA2, with -t permissive
995 "ST3(1010|1721|2120|3230|4340)A",
996 "", "", ""
997 },
998 { "Seagate Medalist 2110, 3221, 4321, 6531, and 8641",
999 "ST3(2110|3221|4321|6531|8641)A",
1000 "", "", ""
1001 },
1002 { "Seagate U Series X family",
1003 "ST3(10014A(CE)?|20014A)",
1004 "", "", ""
1005 },
1006 { "Seagate U8 family",
1007 "ST3(4313|6811|8410|13021|17221)A",
1008 "", "", ""
1009 },
1010 { "Seagate U7 family",
1011 "ST3(30012|40012|60012|80022|120020)A",
1012 "", "", ""
1013 },
1014 { "Seagate U Series 6 family",
1015 "ST3(8002|6002|4081|3061|2041)0A",
1016 "", "", ""
1017 },
1018 { "Seagate U Series 5 family",
1019 "ST3(40823|30621|20413|15311|10211)A",
1020 "", "", ""
1021 },
1022 { "Seagate U4 family",
1023 "ST3(2112|4311|6421|8421)A",
1024 "", "", ""
1025 },
1026 { "Seagate U8 family",
1027 "ST3(8410|4313|17221|13021)A",
1028 "", "", ""
1029 },
1030 { "Seagate U10 family",
1031 "ST3(20423|15323|10212)A",
1032 "", "", ""
1033 },
1034 { "Seagate Barracuda ATA family",
1035 "ST3(2804|2724|2043|1362|1022|681)0A",
1036 "", "", ""
1037 },
1038 { "Seagate Barracuda ATA II family",
1039 "ST3(3063|2042|1532|1021)0A",
1040 "", "", ""
1041 },
1042 { "Seagate Barracuda ATA III family",
1043 "ST3(40824|30620|20414|15310|10215)A",
1044 "", "", ""
1045 },
1046 { "Seagate Barracuda ATA IV family",
1047 "ST3(20011|30011|40016|60021|80021)A",
1048 "", "", ""
1049 },
1050 { "Seagate Barracuda ATA V family",
1051 "ST3(12002(3A|4A|9A|3AS)|800(23A|15A|23AS)|60(015A|210A)|40017A)",
1052 "", "", ""
1053 },
1054 { "Seagate Barracuda 5400.1",
1055 "ST340015A",
1056 "", "", ""
1057 },
1058 { "Seagate Barracuda 7200.7 and 7200.7 Plus family",
1059 "ST3(200021A|200822AS?|16002[13]AS?|12002[26]AS?|1[26]082[78]AS|8001[13]AS?|8081[79]AS|60014A|40111AS|40014AS?)",
1060 "", "", ""
1061 },
1062 { "Seagate Barracuda 7200.8 family",
1063 "ST3(400[68]32|300[68]31|250[68]23|200826)AS?",
1064 "", "", ""
1065 },
1066 { "Seagate Barracuda 7200.9 family",
1067 "ST3(402111?|80[28]110?|120[28]1[0134]|160[28]1[012]|200827|250[68]24|300[68]22|(320|400)[68]33|500[68](32|41))AS?.*",
1068 "", "", ""
1069 },
1070 { "Seagate Barracuda 7200.10 family",
1071 "ST3((80|160)[28]15|200820|250[34]10|(250|300|320|400)[68]20|500[68]30|750[68]40)AS?",
1072 "", "", ""
1073 },
1074 { "Seagate Barracuda 7200.11 family", // unaffected firmware
1075 "ST3(160813|320[68]13|500[368]20|640[36]23|640[35]30|750[36]30|1000(333|[36]40)|1500341)AS?",
1076 "CC.?.?", // http://seagate.custkb.com/seagate/crm/selfservice/search.jsp?DocId=207957
1077 "", ""
1078 },
1079 { "Seagate Barracuda 7200.11 family", // fixed firmware
1080 "ST3(500[368]20|750[36]30|1000340)AS?",
1081 "SD1A", // http://seagate.custkb.com/seagate/crm/selfservice/search.jsp?DocId=207951
1082 "", ""
1083 },
1084 { "Seagate Barracuda 7200.11 family", // fixed firmware
1085 "ST3(160813|320[68]13|640[36]23|1000333|1500341)AS?",
1086 "SD[12]B", // http://seagate.custkb.com/seagate/crm/selfservice/search.jsp?DocId=207957
1087 "", ""
1088 },
1089 { "Seagate Barracuda 7200.11 family", // buggy firmware
1090 "ST3(500[368]20|640[35]30|750[36]30|1000340)AS?",
1091 "(AD14|SD1[5-9])",
1092 "There are known problems with these drives,\n"
1093 "AND THIS FIRMWARE VERSION IS AFFECTED,\n"
1094 "see the following Seagate web pages:\n"
1095 "http://seagate.custkb.com/seagate/crm/selfservice/search.jsp?DocId=207931\n"
1096 "http://seagate.custkb.com/seagate/crm/selfservice/search.jsp?DocId=207951",
1097 ""
1098 },
1099 { "Seagate Barracuda 7200.11 family", // unknown firmware
1100 "ST3(160813|320[68]13|500[368]20|640[36]23|640[35]30|750[36]30|1000(333|[36]40)|1500341)AS?",
1101 "",
1102 "There are known problems with these drives,\n"
1103 "see the following Seagate web pages:\n"
1104 "http://seagate.custkb.com/seagate/crm/selfservice/search.jsp?DocId=207931\n"
1105 "http://seagate.custkb.com/seagate/crm/selfservice/search.jsp?DocId=207951\n"
1106 "http://seagate.custkb.com/seagate/crm/selfservice/search.jsp?DocId=207957",
1107 ""
1108 },
1109 { "Seagate Barracuda 7200.12 family",
1110 "ST3((160|250)318|(320|500)418|500410|(750|1000)528)AS",
1111 "", "", ""
1112 },
1113 { "Seagate Barracuda ES",
1114 "ST3(250[68]2|32062|40062|50063|75064)0NS",
1115 "", "", ""
1116 },
1117 { "Seagate Barracuda ES.2", // fixed firmware
1118 "ST3(25031|50032|75033|100034)0NS",
1119 "SN[01]6", // http://seagate.custkb.com/seagate/crm/selfservice/search.jsp?DocId=207963
1120 "", ""
1121 },
1122 { "Seagate Barracuda ES.2", // unknown firmware
1123 "ST3(25031|50032|75033|100034)0NS",
1124 "",
1125 "There are known problems with these drives,\n"
1126 "see the following Seagate web pages:\n"
1127 "http://seagate.custkb.com/seagate/crm/selfservice/search.jsp?DocId=207931\n"
1128 "http://seagate.custkb.com/seagate/crm/selfservice/search.jsp?DocId=207963",
1129 ""
1130 },
1131 { "Seagate Medalist 17240, 13030, 10231, 8420, and 4310",
1132 "ST3(17240|13030|10231|8420|4310)A",
1133 "", "", ""
1134 },
1135 { "Seagate Medalist 17242, 13032, 10232, 8422, and 4312",
1136 "ST3(1724|1303|1023|842|431)2A",
1137 "", "", ""
1138 },
1139 { "Seagate NL35 family",
1140 "ST3(250623|250823|400632|400832|250824|250624|400633|400833|500641|500841)NS",
1141 "", "", ""
1142 },
1143 { "Seagate SV35.2 Series",
1144 "ST3(160815|250820|320620|500630|750640)(A|S)V",
1145 "", "", ""
1146 },
1147 { "Seagate DB35.3 Series",
1148 "ST3(750640SCE|((80|160)215|(250|320|400)820|500830|750840)(A|S)CE)",
1149 "", "", ""
1150 },
1151 { "Western Digital Protege",
1152 /* Western Digital drives with this comment all appear to use Attribute 9 in
1153 * a non-standard manner. These entries may need to be updated when it
1154 * is understood exactly how Attribute 9 should be interpreted.
1155 * UPDATE: this is probably explained by the WD firmware bug described in the
1156 * smartmontools FAQ */
1157 "WDC WD([2468]00E|1[26]00A)B-.*",
1158 "", "", ""
1159 },
1160 { "Western Digital Caviar family",
1161 /* Western Digital drives with this comment all appear to use Attribute 9 in
1162 * a non-standard manner. These entries may need to be updated when it
1163 * is understood exactly how Attribute 9 should be interpreted.
1164 * UPDATE: this is probably explained by the WD firmware bug described in the
1165 * smartmontools FAQ */
1166 "WDC WD(2|3|4|6|8|10|12|16|18|20|25)00BB-.*",
1167 "", "", ""
1168 },
1169 { "Western Digital Caviar WDxxxAB series",
1170 /* Western Digital drives with this comment all appear to use Attribute 9 in
1171 * a non-standard manner. These entries may need to be updated when it
1172 * is understood exactly how Attribute 9 should be interpreted.
1173 * UPDATE: this is probably explained by the WD firmware bug described in the
1174 * smartmontools FAQ */
1175 "WDC WD(3|4|6|8|25)00AB-.*",
1176 "", "", ""
1177 },
1178 { "Western Digital Caviar WDxxxAA series",
1179 /* Western Digital drives with this comment all appear to use Attribute 9 in
1180 * a non-standard manner. These entries may need to be updated when it
1181 * is understood exactly how Attribute 9 should be interpreted.
1182 * UPDATE: this is probably explained by the WD firmware bug described in the
1183 * smartmontools FAQ */
1184 "WDC WD...?AA(-.*)?",
1185 "", "", ""
1186 },
1187 { "Western Digital Caviar WDxxxBA series",
1188 /* Western Digital drives with this comment all appear to use Attribute 9 in
1189 * a non-standard manner. These entries may need to be updated when it
1190 * is understood exactly how Attribute 9 should be interpreted.
1191 * UPDATE: this is probably explained by the WD firmware bug described in the
1192 * smartmontools FAQ */
1193 "WDC WD...BA",
1194 "", "", ""
1195 },
1196 { "Western Digital Caviar AC series", // add only 5400rpm/7200rpm (ata33 and faster)
1197 "WDC AC((116|121|125|225|132|232)|([1-4][4-9][0-9])|([1-4][0-9][0-9][0-9]))00[A-Z]?.*",
1198 "", "", ""
1199 },
1200 { "Western Digital Caviar SE family",
1201 /* Western Digital drives with this comment all appear to use Attribute 9 in
1202 * a non-standard manner. These entries may need to be updated when it
1203 * is understood exactly how Attribute 9 should be interpreted.
1204 * UPDATE: this is probably explained by the WD firmware bug described in the
1205 * smartmontools FAQ
1206 * UPDATE 2: this does not apply to more recent models, at least WD3200AAJB */
1207 "WDC WD(4|6|8|10|12|16|18|20|25|30|32|40|50)00(JB|PB)-.*",
1208 "", "", ""
1209 },
1210 { "Western Digital Caviar Blue EIDE family", // WD Caviar SE EIDE family
1211 /* not completely accurate: at least also WD800JB, WD(4|8|20|25)00BB sold as Caviar Blue */
1212 "WDC WD(16|25|32|40|50)00AAJB-.*",
1213 "", "", ""
1214 },
1215 { "Western Digital Caviar Blue EIDE family", // WD Caviar SE16 EIDE family
1216 "WDC WD(25|32|40|50)00AAKB-.*",
1217 "", "", ""
1218 },
1219 { "Western Digital RE EIDE family",
1220 "WDC WD(12|16|25|32)00SB-.*",
1221 "", "", ""
1222 },
1223 { "Western Digital Caviar Serial ATA family",
1224 "WDC WD(4|8|20|32)00BD-.*",
1225 "", "", ""
1226 },
1227 { "Western Digital Caviar SE Serial ATA family",
1228 "WDC WD(4|8|12|16|20|25|32|40)00(JD|KD|PD)-.*",
1229 "", "", ""
1230 },
1231 { "Western Digital Caviar SE Serial ATA family",
1232 "WDC WD(8|12|16|20|25|30|32|40|50)00JS-.*",
1233 "", "", ""
1234 },
1235 { "Western Digital Caviar SE16 Serial ATA family",
1236 "WDC WD(16|20|25|32|40|50|75)00KS-.*",
1237 "", "", ""
1238 },
1239 { "Western Digital Caviar Blue Serial ATA family", // WD Caviar SE Serial ATA family
1240 /* not completely accurate: at least also WD800BD, (4|8)00JD sold as Caviar Blue */
1241 "WDC WD((8|12|16|25|32)00AABS|(12|16|25|32|40|50)00AAJS)-.*",
1242 "", "", ""
1243 },
1244 { "Western Digital Caviar Blue Serial ATA family", // WD Caviar SE16 Serial ATA family
1245 "WDC WD(16|20|25|32|40|50|64|75)00AAKS-.*",
1246 "", "", ""
1247 },
1248 { "Western Digital RE Serial ATA family",
1249 "WDC WD(12|16|25|32)00(SD|YD|YS)-.*",
1250 "", "", ""
1251 },
1252 { "Western Digital RE2 Serial ATA family",
1253 "WDC WD((40|50|75)00(YR|YS|AYYS)|(16|32|40|50)0[01]ABYS)-.*",
1254 "", "", ""
1255 },
1256 { "Western Digital RE2-GP family",
1257 "WDC WD(5000AB|7500AY|1000FY)PS-.*",
1258 "", "", ""
1259 },
1260 { "Western Digital RE3 Serial ATA family",
1261 "WDC WD((25|32|50)02A|(75|10)02F)BYS-.*",
1262 "", "", ""
1263 },
1264 { "Western Digital Caviar Green family",
1265 "WDC WD((50|64|75)00AA(C|V)S|(50|75)00AADS|10EA(C|V)S|(10|15|20)EADS)-.*",
1266 "", "", ""
1267 },
1268 { "Western Digital Caviar Black family",
1269 "WDC WD((500|640|750)1AA|1001FA)LS-.*",
1270 "", "", ""
1271 },
1272 { "Western Digital AV ATA family",
1273 "WDC WD(8|16|50)00AV(B|J)B-.*",
1274 "", "", ""
1275 },
1276 { "Western Digital AV-GP family",
1277 "WDC WD((16|25|32|50|64|75)00AVVS|(50|75)00AVCS|10EVVS|(10|20)EVCS|WD(10|15|20)EVDS)-.*",
1278 "", "", ""
1279 },
1280 { "Western Digital Raptor family",
1281 "WDC WD((360|740|800)GD|(360|740|1500)ADF[DS])-.*",
1282 "", "", ""
1283 },
1284 { "Western Digital Raptor X",
1285 "WDC WD1500AHFD-.*",
1286 "", "", ""
1287 },
1288 { "Western Digital VelociRaptor family",
1289 "WDC WD((1500|3000)B|3000G)LFS-.*",
1290 "", "", ""
1291 },
1292 { "Western Digital Scorpio EIDE family",
1293 "WDC WD(4|6|8|10|12|16)00(UE|VE)-.*",
1294 "", "", ""
1295 },
1296 { "Western Digital Scorpio Blue EIDE family",
1297 "WDC WD(4|6|8|10|12|16|25)00BEVE-.*",
1298 "", "", ""
1299 },
1300 { "Western Digital Scorpio Serial ATA family",
1301 "WDC WD(4|6|8|10|12|16|25)00BEAS-.*",
1302 "", "", ""
1303 },
1304 { "Western Digital Scorpio Blue Serial ATA family",
1305 "WDC WD((4|6|8|10|12|16|25)00BEVS|(8|12|16|25|32|40|50)00BEVT)-.*",
1306 "", "", ""
1307 },
1308 { "Western Digital Scorpio Black Serial ATA family",
1309 "WDC WD(8|12|16|25|32)00B[EJ]KT-.*",
1310 "", "", ""
1311 },
1312 { "Western Digital My Passport Essential hard drive (USB interface)",
1313 "WDC WD3200BMVU-.*",
1314 "", "", ""
1315 },
1316 { "Western Digital My Passport hard drive (USB interface)",
1317 "WDC WD3200BMVV-.*",
1318 "", "", ""
1319 },
1320 { "Quantum Bigfoot series",
1321 "QUANTUM BIGFOOT TS10.0A",
1322 "", "", ""
1323 },
1324 { "Quantum Fireball lct15 series",
1325 "QUANTUM FIREBALLlct15 ([123]0|22)",
1326 "", "", ""
1327 },
1328 { "Quantum Fireball lct20 series",
1329 "QUANTUM FIREBALLlct20 [234]0",
1330 "", "", ""
1331 },
1332 { "Quantum Fireball CX series",
1333 "QUANTUM FIREBALL CX10.2A",
1334 "", "", ""
1335 },
1336 { "Quantum Fireball CR series",
1337 "QUANTUM FIREBALL CR(4.3|6.4|8.4|13.0)A",
1338 "", "", ""
1339 },
1340 { "Quantum Fireball EX series",
1341 "QUANTUM FIREBALL EX(3.2|6.4)A",
1342 "", "", ""
1343 },
1344 { "Quantum Fireball ST series",
1345 "QUANTUM FIREBALL ST(3.2|4.3|4300)A",
1346 "", "", ""
1347 },
1348 { "Quantum Fireball SE series",
1349 "QUANTUM FIREBALL SE4.3A",
1350 "", "", ""
1351 },
1352 { "Quantum Fireball Plus LM series",
1353 "QUANTUM FIREBALLP LM(10.2|15|20.[45]|30)",
1354 "", "", ""
1355 },
1356 { "Quantum Fireball Plus AS series",
1357 "QUANTUM FIREBALLP AS(10.2|20.5|30.0|40.0)",
1358 "", "", ""
1359 },
1360 { "Quantum Fireball Plus KX series",
1361 "QUANTUM FIREBALLP KX27.3",
1362 "", "", ""
1363 },
1364 { "Quantum Fireball Plus KA series",
1365 "QUANTUM FIREBALLP KA(9|10).1",
1366 "", "", ""
1367 },
1368 // END drivedb.h (DO NOT DELETE - used by Makefile)
1369 };
1370
1371
1372 /// Drive database class. Stores custom entries read from file.
1373 /// Provides transparent access to concatenation of custom and
1374 /// default table.
1375 class drive_database
1376 {
1377 public:
1378 drive_database();
1379
1380 ~drive_database();
1381
1382 /// Get total number of entries.
1383 unsigned size() const
1384 { return m_custom_tab.size() + m_builtin_size; }
1385
1386 /// Get number of custom entries.
1387 unsigned custom_size() const
1388 { return m_custom_tab.size(); }
1389
1390 /// Array access.
1391 const drive_settings & operator[](unsigned i);
1392
1393 /// Append new custom entry.
1394 void push_back(const drive_settings & src);
1395
1396 /// Append builtin table.
1397 void append(const drive_settings * builtin_tab, unsigned builtin_size)
1398 { m_builtin_tab = builtin_tab; m_builtin_size = builtin_size; }
1399
1400 private:
1401 const drive_settings * m_builtin_tab;
1402 unsigned m_builtin_size;
1403
1404 std::vector<drive_settings> m_custom_tab;
1405 std::vector<char *> m_custom_strings;
1406
1407 const char * copy_string(const char * str);
1408
1409 drive_database(const drive_database &);
1410 void operator=(const drive_database &);
1411 };
1412
1413 drive_database::drive_database()
1414 : m_builtin_tab(0), m_builtin_size(0)
1415 {
1416 }
1417
1418 drive_database::~drive_database()
1419 {
1420 for (unsigned i = 0; i < m_custom_strings.size(); i++)
1421 delete [] m_custom_strings[i];
1422 }
1423
1424 const drive_settings & drive_database::operator[](unsigned i)
1425 {
1426 return (i < m_custom_tab.size() ? m_custom_tab[i]
1427 : m_builtin_tab[i - m_custom_tab.size()] );
1428 }
1429
1430 void drive_database::push_back(const drive_settings & src)
1431 {
1432 drive_settings dest;
1433 dest.modelfamily = copy_string(src.modelfamily);
1434 dest.modelregexp = copy_string(src.modelregexp);
1435 dest.firmwareregexp = copy_string(src.firmwareregexp);
1436 dest.warningmsg = copy_string(src.warningmsg);
1437 dest.presets = copy_string(src.presets);
1438 m_custom_tab.push_back(dest);
1439 }
1440
1441 const char * drive_database::copy_string(const char * src)
1442 {
1443 char * dest = new char[strlen(src)+1];
1444 try {
1445 m_custom_strings.push_back(dest);
1446 }
1447 catch (...) {
1448 delete [] dest; throw;
1449 }
1450 return strcpy(dest, src);
1451 }
1452
1453
1454 /// The drive database.
1455 static drive_database knowndrives;
1456
1457
1458 // Compile regular expression, print message on failure.
1459 static bool compile(regular_expression & regex, const char *pattern)
1460 {
1461 if (!regex.compile(pattern, REG_EXTENDED)) {
1462 pout("Internal error: unable to compile regular expression \"%s\": %s\n"
1463 "Please inform smartmontools developers at " PACKAGE_BUGREPORT "\n",
1464 pattern, regex.get_errmsg());
1465 return false;
1466 }
1467 return true;
1468 }
1469
1470 // Compile & match a regular expression.
1471 static bool match(const char * pattern, const char * str)
1472 {
1473 regular_expression regex;
1474 if (!compile(regex, pattern))
1475 return false;
1476 return regex.full_match(str);
1477 }
1478
1479 // Searches knowndrives[] for a drive with the given model number and firmware
1480 // string. If either the drive's model or firmware strings are not set by the
1481 // manufacturer then values of NULL may be used. Returns the entry of the
1482 // first match in knowndrives[] or 0 if no match if found.
1483 const drive_settings * lookup_drive(const char * model, const char * firmware)
1484 {
1485 if (!model)
1486 model = "";
1487 if (!firmware)
1488 firmware = "";
1489
1490 for (unsigned i = 0; i < knowndrives.size(); i++) {
1491 // Check whether model matches the regular expression in knowndrives[i].
1492 if (!match(knowndrives[i].modelregexp, model))
1493 continue;
1494
1495 // Model matches, now check firmware. "" matches always.
1496 if (!( !*knowndrives[i].firmwareregexp
1497 || match(knowndrives[i].firmwareregexp, firmware)))
1498 continue;
1499
1500 // Found
1501 return &knowndrives[i];
1502 }
1503
1504 // Not found
1505 return 0;
1506 }
1507
1508 // Parse '-v' and '-F' options in preset string, return false on error.
1509 static bool parse_presets(const char * presets, ata_vendor_attr_defs & defs,
1510 unsigned char & fix_firmwarebug)
1511 {
1512 for (int i = 0; ; ) {
1513 i += strspn(presets+i, " \t");
1514 if (!presets[i])
1515 break;
1516 char opt, arg[40+1+13]; int len = -1;
1517 if (!(sscanf(presets+i, "-%c %40[^ ]%n", &opt, arg, &len) >= 2 && len > 0))
1518 return false;
1519 if (opt == 'v') {
1520 // Parse "-v N,format[,name]"
1521 if (!parse_attribute_def(arg, defs, PRIOR_DATABASE))
1522 return false;
1523 }
1524 else if (opt == 'F') {
1525 unsigned char fix;
1526 if (!strcmp(arg, "samsung"))
1527 fix = FIX_SAMSUNG;
1528 else if (!strcmp(arg, "samsung2"))
1529 fix = FIX_SAMSUNG2;
1530 else if (!strcmp(arg, "samsung3"))
1531 fix = FIX_SAMSUNG3;
1532 else
1533 return false;
1534 // Set only if not set by user
1535 if (fix_firmwarebug == FIX_NOTSPECIFIED)
1536 fix_firmwarebug = fix;
1537 }
1538 else
1539 return false;
1540
1541 i += len;
1542 }
1543 return true;
1544 }
1545
1546 // Shows one entry of knowndrives[], returns #errors.
1547 static int showonepreset(const drive_settings * dbentry)
1548 {
1549 // Basic error check
1550 if (!( dbentry
1551 && dbentry->modelfamily
1552 && dbentry->modelregexp && *dbentry->modelregexp
1553 && dbentry->firmwareregexp
1554 && dbentry->warningmsg
1555 && dbentry->presets )) {
1556 pout("Invalid drive database entry. Please report\n"
1557 "this error to smartmontools developers at " PACKAGE_BUGREPORT ".\n");
1558 return 1;
1559 }
1560
1561 // print and check model and firmware regular expressions
1562 int errcnt = 0;
1563 regular_expression regex;
1564 pout("%-*s %s\n", TABLEPRINTWIDTH, "MODEL REGEXP:", dbentry->modelregexp);
1565 if (!compile(regex, dbentry->modelregexp))
1566 errcnt++;
1567
1568 pout("%-*s %s\n", TABLEPRINTWIDTH, "FIRMWARE REGEXP:", *dbentry->firmwareregexp ?
1569 dbentry->firmwareregexp : ".*"); // preserve old output (TODO: Change)
1570 if (*dbentry->firmwareregexp && !compile(regex, dbentry->firmwareregexp))
1571 errcnt++;
1572
1573 pout("%-*s %s\n", TABLEPRINTWIDTH, "MODEL FAMILY:", dbentry->modelfamily);
1574
1575 // if there are any presets, then show them
1576 unsigned char fix_firmwarebug = 0;
1577 bool first_preset = true;
1578 if (*dbentry->presets) {
1579 ata_vendor_attr_defs defs;
1580 if (!parse_presets(dbentry->presets, defs, fix_firmwarebug)) {
1581 pout("Syntax error in preset option string \"%s\"\n", dbentry->presets);
1582 errcnt++;
1583 }
1584 for (int i = 0; i < MAX_ATTRIBUTE_NUM; i++) {
1585 if (defs[i].priority != PRIOR_DEFAULT) {
1586 // Use leading zeros instead of spaces so that everything lines up.
1587 pout("%-*s %03d %s\n", TABLEPRINTWIDTH, first_preset ? "ATTRIBUTE OPTIONS:" : "",
1588 i, ata_get_smart_attr_name(i, defs).c_str());
1589 first_preset = false;
1590 }
1591 }
1592 }
1593 if (first_preset)
1594 pout("%-*s %s\n", TABLEPRINTWIDTH, "ATTRIBUTE OPTIONS:", "None preset; no -v options are required.");
1595
1596 // describe firmwarefix
1597 if (fix_firmwarebug) {
1598 const char * fixdesc;
1599 switch (fix_firmwarebug) {
1600 case FIX_SAMSUNG:
1601 fixdesc = "Fixes byte order in some SMART data (same as -F samsung)";
1602 break;
1603 case FIX_SAMSUNG2:
1604 fixdesc = "Fixes byte order in some SMART data (same as -F samsung2)";
1605 break;
1606 case FIX_SAMSUNG3:
1607 fixdesc = "Fixes completed self-test reported as in progress (same as -F samsung3)";
1608 break;
1609 default:
1610 fixdesc = "UNKNOWN"; errcnt++;
1611 break;
1612 }
1613 pout("%-*s %s\n", TABLEPRINTWIDTH, "OTHER PRESETS:", fixdesc);
1614 }
1615
1616 // Print any special warnings
1617 if (*dbentry->warningmsg)
1618 pout("%-*s %s\n", TABLEPRINTWIDTH, "WARNINGS:", dbentry->warningmsg);
1619 return errcnt;
1620 }
1621
1622 // Shows all presets for drives in knowndrives[].
1623 // Returns #syntax errors.
1624 int showallpresets()
1625 {
1626 // loop over all entries in the knowndrives[] table, printing them
1627 // out in a nice format
1628 int errcnt = 0;
1629 for (unsigned i = 0; i < knowndrives.size(); i++) {
1630 errcnt += showonepreset(&knowndrives[i]);
1631 pout("\n");
1632 }
1633
1634 pout("Total number of entries :%5u\n"
1635 "Entries read from file(s):%5u\n\n",
1636 knowndrives.size(), knowndrives.custom_size());
1637
1638 pout("For information about adding a drive to the database see the FAQ on the\n");
1639 pout("smartmontools home page: " PACKAGE_HOMEPAGE "\n");
1640
1641 if (errcnt > 0)
1642 pout("\nFound %d syntax error(s) in database.\n"
1643 "Please inform smartmontools developers at " PACKAGE_BUGREPORT "\n", errcnt);
1644 return errcnt;
1645 }
1646
1647 // Shows all matching presets for a drive in knowndrives[].
1648 // Returns # matching entries.
1649 int showmatchingpresets(const char *model, const char *firmware)
1650 {
1651 int cnt = 0;
1652 const char * firmwaremsg = (firmware ? firmware : "(any)");
1653
1654 for (unsigned i = 0; i < knowndrives.size(); i++) {
1655 if (!match(knowndrives[i].modelregexp, model))
1656 continue;
1657 if ( firmware && *knowndrives[i].firmwareregexp
1658 && !match(knowndrives[i].firmwareregexp, firmware))
1659 continue;
1660 // Found
1661 if (++cnt == 1)
1662 pout("Drive found in smartmontools Database. Drive identity strings:\n"
1663 "%-*s %s\n"
1664 "%-*s %s\n"
1665 "match smartmontools Drive Database entry:\n",
1666 TABLEPRINTWIDTH, "MODEL:", model, TABLEPRINTWIDTH, "FIRMWARE:", firmwaremsg);
1667 else if (cnt == 2)
1668 pout("and match these additional entries:\n");
1669 showonepreset(&knowndrives[i]);
1670 pout("\n");
1671 }
1672 if (cnt == 0)
1673 pout("No presets are defined for this drive. Its identity strings:\n"
1674 "MODEL: %s\n"
1675 "FIRMWARE: %s\n"
1676 "do not match any of the known regular expressions.\n",
1677 model, firmwaremsg);
1678 return cnt;
1679 }
1680
1681 // Shows the presets (if any) that are available for the given drive.
1682 void show_presets(const ata_identify_device * drive, bool fix_swapped_id)
1683 {
1684 char model[MODEL_STRING_LENGTH+1], firmware[FIRMWARE_STRING_LENGTH+1];
1685
1686 // get the drive's model/firmware strings
1687 format_ata_string(model, drive->model, MODEL_STRING_LENGTH, fix_swapped_id);
1688 format_ata_string(firmware, drive->fw_rev, FIRMWARE_STRING_LENGTH, fix_swapped_id);
1689
1690 // and search to see if they match values in the table
1691 const drive_settings * dbentry = lookup_drive(model, firmware);
1692 if (!dbentry) {
1693 // no matches found
1694 pout("No presets are defined for this drive. Its identity strings:\n"
1695 "MODEL: %s\n"
1696 "FIRMWARE: %s\n"
1697 "do not match any of the known regular expressions.\n"
1698 "Use -P showall to list all known regular expressions.\n",
1699 model, firmware);
1700 return;
1701 }
1702
1703 // We found a matching drive. Print out all information about it.
1704 pout("Drive found in smartmontools Database. Drive identity strings:\n"
1705 "%-*s %s\n"
1706 "%-*s %s\n"
1707 "match smartmontools Drive Database entry:\n",
1708 TABLEPRINTWIDTH, "MODEL:", model, TABLEPRINTWIDTH, "FIRMWARE:", firmware);
1709 showonepreset(dbentry);
1710 }
1711
1712 // Sets preset vendor attribute options in opts by finding the entry
1713 // (if any) for the given drive in knowndrives[]. Values that have
1714 // already been set in opts will not be changed. Returns false if drive
1715 // not recognized.
1716 bool apply_presets(const ata_identify_device *drive, ata_vendor_attr_defs & defs,
1717 unsigned char & fix_firmwarebug, bool fix_swapped_id)
1718 {
1719 // get the drive's model/firmware strings
1720 char model[MODEL_STRING_LENGTH+1], firmware[FIRMWARE_STRING_LENGTH+1];
1721 format_ata_string(model, drive->model, MODEL_STRING_LENGTH, fix_swapped_id);
1722 format_ata_string(firmware, drive->fw_rev, FIRMWARE_STRING_LENGTH, fix_swapped_id);
1723
1724 // Look up the drive in knowndrives[].
1725 const drive_settings * dbentry = lookup_drive(model, firmware);
1726 if (!dbentry)
1727 return false;
1728
1729 if (*dbentry->presets) {
1730 // Apply presets
1731 if (!parse_presets(dbentry->presets, defs, fix_firmwarebug))
1732 pout("Syntax error in preset option string \"%s\"\n", dbentry->presets);
1733 }
1734 return true;
1735 }
1736
1737
1738 /////////////////////////////////////////////////////////////////////////////
1739 // Parser for drive database files
1740
1741 // Abstract pointer to read file input.
1742 // Operations supported: c = *p; c = p[1]; ++p;
1743 class stdin_iterator
1744 {
1745 public:
1746 explicit stdin_iterator(FILE * f)
1747 : m_f(f) { get(); get(); }
1748
1749 stdin_iterator & operator++()
1750 { get(); return *this; }
1751
1752 char operator*() const
1753 { return m_c; }
1754
1755 char operator[](int i) const
1756 {
1757 if (i != 1)
1758 fail();
1759 return m_next;
1760 }
1761
1762 private:
1763 FILE * m_f;
1764 char m_c, m_next;
1765 void get();
1766 void fail() const;
1767 };
1768
1769 void stdin_iterator::get()
1770 {
1771 m_c = m_next;
1772 int ch = getc(m_f);
1773 m_next = (ch != EOF ? ch : 0);
1774 }
1775
1776 void stdin_iterator::fail() const
1777 {
1778 throw std::runtime_error("stdin_iterator: wrong usage");
1779 }
1780
1781
1782 // Use above as parser input 'pointer'. Can easily be changed later
1783 // to e.g. 'const char *' if above is too slow.
1784 typedef stdin_iterator parse_ptr;
1785
1786 // Skip whitespace and comments.
1787 static parse_ptr skip_white(parse_ptr src, const char * path, int & line)
1788 {
1789 for ( ; ; ++src) switch (*src) {
1790 case ' ': case '\t':
1791 continue;
1792
1793 case '\n':
1794 ++line;
1795 continue;
1796
1797 case '/':
1798 switch (src[1]) {
1799 case '/':
1800 // skip '// comment'
1801 ++src; ++src;
1802 while (*src && *src != '\n')
1803 ++src;
1804 if (*src)
1805 ++line;
1806 break;
1807 case '*':
1808 // skip '/* comment */'
1809 ++src; ++src;
1810 for (;;) {
1811 if (!*src) {
1812 pout("%s(%d): Missing '*/'\n", path, line);
1813 return src;
1814 }
1815 char c = *src; ++src;
1816 if (c == '\n')
1817 ++line;
1818 else if (c == '*' && *src == '/')
1819 break;
1820 }
1821 break;
1822 default:
1823 return src;
1824 }
1825 continue;
1826
1827 default:
1828 return src;
1829 }
1830 }
1831
1832 // Info about a token.
1833 struct token_info
1834 {
1835 char type;
1836 int line;
1837 std::string value;
1838
1839 token_info() : type(0), line(0) { }
1840 };
1841
1842 // Get next token.
1843 static parse_ptr get_token(parse_ptr src, token_info & token, const char * path, int & line)
1844 {
1845 src = skip_white(src, path, line);
1846 switch (*src) {
1847 case '{': case '}': case ',':
1848 // Simple token
1849 token.type = *src; token.line = line;
1850 ++src;
1851 break;
1852
1853 case '"':
1854 // String constant
1855 token.type = '"'; token.line = line;
1856 token.value = "";
1857 do {
1858 for (++src; *src != '"'; ++src) {
1859 char c = *src;
1860 if (!c || c == '\n' || (c == '\\' && !src[1])) {
1861 pout("%s(%d): Missing terminating '\"'\n", path, line);
1862 token.type = '?'; token.line = line;
1863 return src;
1864 }
1865 if (c == '\\') {
1866 c = *++src;
1867 switch (c) {
1868 case 'n' : c = '\n'; break;
1869 case '\n': ++line; break;
1870 case '\\': case '"': break;
1871 default:
1872 pout("%s(%d): Unknown escape sequence '\\%c'\n", path, line, c);
1873 token.type = '?'; token.line = line;
1874 continue;
1875 }
1876 }
1877 token.value += c;
1878 }
1879 // Lookahead to detect string constant concatentation
1880 src = skip_white(++src, path, line);
1881 } while (*src == '"');
1882 break;
1883
1884 case 0:
1885 // EOF
1886 token.type = 0; token.line = line;
1887 break;
1888
1889 default:
1890 pout("%s(%d): Syntax error, invalid char '%c'\n", path, line, *src);
1891 token.type = '?'; token.line = line;
1892 while (*src && *src != '\n')
1893 ++src;
1894 break;
1895 }
1896
1897 return src;
1898 }
1899
1900 // Parse drive database from abstract input pointer.
1901 static bool parse_drive_database(parse_ptr src, drive_database & db, const char * path)
1902 {
1903 int state = 0, field = 0;
1904 std::string values[5];
1905 bool ok = true;
1906
1907 token_info token; int line = 1;
1908 src = get_token(src, token, path, line);
1909 for (;;) {
1910 // EOF is ok after '}', trailing ',' is also allowed.
1911 if (!token.type && (state == 0 || state == 4))
1912 break;
1913
1914 // Check expected token
1915 const char expect[] = "{\",},";
1916 if (token.type != expect[state]) {
1917 if (token.type != '?')
1918 pout("%s(%d): Syntax error, '%c' expected\n", path, token.line, expect[state]);
1919 ok = false;
1920 // Skip to next entry
1921 while (token.type && token.type != '{')
1922 src = get_token(src, token, path, line);
1923 state = 0;
1924 if (token.type)
1925 continue;
1926 break;
1927 }
1928
1929 // Interpret parser state
1930 switch (state) {
1931 case 0: // ... ^{...}
1932 state = 1; field = 0;
1933 break;
1934 case 1: // {... ^"..." ...}
1935 switch (field) {
1936 case 1: case 2:
1937 if (!token.value.empty()) {
1938 regular_expression regex;
1939 if (!regex.compile(token.value.c_str(), REG_EXTENDED)) {
1940 pout("%s(%d): Error in regular expression: %s\n", path, token.line, regex.get_errmsg());
1941 ok = false;
1942 }
1943 }
1944 else if (field == 1) {
1945 pout("%s(%d): Missing regular expression for drive model\n", path, token.line);
1946 ok = false;
1947 }
1948 break;
1949 case 4:
1950 if (!token.value.empty()) {
1951 ata_vendor_attr_defs defs; unsigned char fix = 0;
1952 if (!parse_presets(token.value.c_str(), defs, fix)) {
1953 pout("%s(%d): Syntax error in preset option string\n", path, token.line);
1954 ok = false;
1955 }
1956 }
1957 break;
1958 }
1959 values[field] = token.value;
1960 state = (++field < 5 ? 2 : 3);
1961 break;
1962 case 2: // {... "..."^, ...}
1963 state = 1;
1964 break;
1965 case 3: // {...^}, ...
1966 {
1967 drive_settings entry;
1968 entry.modelfamily = values[0].c_str();
1969 entry.modelregexp = values[1].c_str();
1970 entry.firmwareregexp = values[2].c_str();
1971 entry.warningmsg = values[3].c_str();
1972 entry.presets = values[4].c_str();
1973 db.push_back(entry);
1974 }
1975 state = 4;
1976 break;
1977 case 4: // {...}^, ...
1978 state = 0;
1979 break;
1980 default:
1981 pout("Bad state %d\n", state);
1982 return false;
1983 }
1984 src = get_token(src, token, path, line);
1985 }
1986 return ok;
1987 }
1988
1989 // Read drive database from file.
1990 bool read_drive_database(const char * path)
1991 {
1992 stdio_file f(path, "r");
1993 if (!f) {
1994 pout("%s: cannot open drive database file\n", path);
1995 return false;
1996 }
1997
1998 return parse_drive_database(parse_ptr(f), knowndrives, path);
1999 }
2000
2001 // Read drive databases from standard places.
2002 bool read_default_drive_databases()
2003 {
2004 #ifndef _WIN32
2005 // Read file for local additions: /{,usr/local/}etc/smart_drivedb.h
2006 static const char db1[] = SMARTMONTOOLS_SYSCONFDIR"/smart_drivedb.h";
2007 #else
2008 static const char db1[] = "./smart_drivedb.h";
2009 #endif
2010 if (!access(db1, 0)) {
2011 if (!read_drive_database(db1))
2012 return false;
2013 }
2014
2015 #ifdef SMARTMONTOOLS_DRIVEDBDIR
2016 // Read file from package: // /usr/{,local/}share/smartmontools/drivedb.h
2017 static const char db2[] = SMARTMONTOOLS_DRIVEDBDIR"/drivedb.h";
2018 if (!access(db2, 0)) {
2019 if (!read_drive_database(db2))
2020 return false;
2021 }
2022 else
2023 #endif
2024 {
2025 // Append builtin table.
2026 knowndrives.append(builtin_knowndrives,
2027 sizeof(builtin_knowndrives)/sizeof(builtin_knowndrives[0]));
2028 }
2029
2030 return true;
2031 }