4 * Home page of code is: http://www.smartmontools.org
6 * Copyright (C) 2003-11 Philip Williams, Bruce Allen
7 * Copyright (C) 2008-16 Christian Franke
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2, or (at your option)
14 * You should have received a copy of the GNU General Public License
15 * (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
23 #include "knowndrives.h"
30 #include <io.h> // access()
35 const char * knowndrives_cpp_cvsid
= "$Id: knowndrives.cpp 4208 2016-01-22 19:45:35Z chrfranke $"
38 #define MODEL_STRING_LENGTH 40
39 #define FIRMWARE_STRING_LENGTH 8
40 #define TABLEPRINTWIDTH 19
43 // Builtin table of known drives.
44 // Used as a default if not read from
45 // "/usr/{,/local}share/smartmontools/drivedb.h"
46 // or any other file specified by '-B' option,
47 // see read_default_drive_databases() below.
48 // The drive_settings structure is described in drivedb.h.
49 const drive_settings builtin_knowndrives
[] = {
53 const unsigned builtin_knowndrives_size
=
54 sizeof(builtin_knowndrives
) / sizeof(builtin_knowndrives
[0]);
56 /// Drive database class. Stores custom entries read from file.
57 /// Provides transparent access to concatenation of custom and
66 /// Get total number of entries.
68 { return m_custom_tab
.size() + m_builtin_size
; }
70 /// Get number of custom entries.
71 unsigned custom_size() const
72 { return m_custom_tab
.size(); }
75 const drive_settings
& operator[](unsigned i
);
77 /// Append new custom entry.
78 void push_back(const drive_settings
& src
);
80 /// Append builtin table.
81 void append(const drive_settings
* builtin_tab
, unsigned builtin_size
)
82 { m_builtin_tab
= builtin_tab
; m_builtin_size
= builtin_size
; }
85 const drive_settings
* m_builtin_tab
;
86 unsigned m_builtin_size
;
88 std::vector
<drive_settings
> m_custom_tab
;
89 std::vector
<char *> m_custom_strings
;
91 const char * copy_string(const char * str
);
93 drive_database(const drive_database
&);
94 void operator=(const drive_database
&);
97 drive_database::drive_database()
98 : m_builtin_tab(0), m_builtin_size(0)
102 drive_database::~drive_database()
104 for (unsigned i
= 0; i
< m_custom_strings
.size(); i
++)
105 delete [] m_custom_strings
[i
];
108 const drive_settings
& drive_database::operator[](unsigned i
)
110 return (i
< m_custom_tab
.size() ? m_custom_tab
[i
]
111 : m_builtin_tab
[i
- m_custom_tab
.size()] );
114 void drive_database::push_back(const drive_settings
& src
)
117 dest
.modelfamily
= copy_string(src
.modelfamily
);
118 dest
.modelregexp
= copy_string(src
.modelregexp
);
119 dest
.firmwareregexp
= copy_string(src
.firmwareregexp
);
120 dest
.warningmsg
= copy_string(src
.warningmsg
);
121 dest
.presets
= copy_string(src
.presets
);
122 m_custom_tab
.push_back(dest
);
125 const char * drive_database::copy_string(const char * src
)
127 size_t len
= strlen(src
);
128 char * dest
= new char[len
+1];
129 memcpy(dest
, src
, len
+1);
131 m_custom_strings
.push_back(dest
);
134 delete [] dest
; throw;
140 /// The drive database.
141 static drive_database knowndrives
;
150 // Return type of entry
151 static dbentry_type
get_modelfamily_type(const char * modelfamily
)
153 if (modelfamily
[0] == 'D' && !strcmp(modelfamily
, "DEFAULT"))
154 return DBENTRY_ATA_DEFAULT
;
155 else if(modelfamily
[0] == 'U' && str_starts_with(modelfamily
, "USB:"))
161 static inline dbentry_type
get_dbentry_type(const drive_settings
* dbentry
)
163 return get_modelfamily_type(dbentry
->modelfamily
);
166 // Compile regular expression, print message on failure.
167 static bool compile(regular_expression
& regex
, const char *pattern
)
169 if (!regex
.compile(pattern
, REG_EXTENDED
)) {
170 pout("Internal error: unable to compile regular expression \"%s\": %s\n"
171 "Please inform smartmontools developers at " PACKAGE_BUGREPORT
"\n",
172 pattern
, regex
.get_errmsg());
178 // Compile & match a regular expression.
179 static bool match(const char * pattern
, const char * str
)
181 regular_expression regex
;
182 if (!compile(regex
, pattern
))
184 return regex
.full_match(str
);
187 // Searches knowndrives[] for a drive with the given model number and firmware
188 // string. If either the drive's model or firmware strings are not set by the
189 // manufacturer then values of NULL may be used. Returns the entry of the
190 // first match in knowndrives[] or 0 if no match if found.
191 static const drive_settings
* lookup_drive(const char * model
, const char * firmware
)
198 for (unsigned i
= 0; i
< knowndrives
.size(); i
++) {
199 // Skip DEFAULT and USB entries
200 if (get_dbentry_type(&knowndrives
[i
]) != DBENTRY_ATA
)
203 // Check whether model matches the regular expression in knowndrives[i].
204 if (!match(knowndrives
[i
].modelregexp
, model
))
207 // Model matches, now check firmware. "" matches always.
208 if (!( !*knowndrives
[i
].firmwareregexp
209 || match(knowndrives
[i
].firmwareregexp
, firmware
)))
213 return &knowndrives
[i
];
221 // Parse drive or USB options in preset string, return false on error.
222 static bool parse_db_presets(const char * presets
, ata_vendor_attr_defs
* defs
,
223 firmwarebug_defs
* firmwarebugs
, std::string
* type
)
225 for (int i
= 0; ; ) {
226 i
+= strspn(presets
+i
, " \t");
229 char opt
, arg
[80+1+13]; int len
= -1;
230 if (!(sscanf(presets
+i
, "-%c %80[^ ]%n", &opt
, arg
, &len
) >= 2 && len
> 0))
232 if (opt
== 'v' && defs
) {
233 // Parse "-v N,format[,name[,HDD|SSD]]"
234 if (!parse_attribute_def(arg
, *defs
, (firmwarebugs
? PRIOR_DATABASE
: PRIOR_DEFAULT
)))
237 else if (opt
== 'F' && firmwarebugs
) {
238 firmwarebug_defs bug
;
239 if (!parse_firmwarebug_def(arg
, bug
))
241 // Don't set if user specified '-F none'.
242 if (!firmwarebugs
->is_set(BUG_NONE
))
243 firmwarebugs
->set(bug
);
245 else if (opt
== 'd' && type
) {
246 // TODO: Check valid types
257 // Parse '-v' options in default preset string, return false on error.
258 static inline bool parse_default_presets(const char * presets
,
259 ata_vendor_attr_defs
& defs
)
261 return parse_db_presets(presets
, &defs
, 0, 0);
264 // Parse '-v' and '-F' options in preset string, return false on error.
265 static inline bool parse_presets(const char * presets
,
266 ata_vendor_attr_defs
& defs
,
267 firmwarebug_defs
& firmwarebugs
)
269 return parse_db_presets(presets
, &defs
, &firmwarebugs
, 0);
272 // Parse '-d' option in preset string, return false on error.
273 static inline bool parse_usb_type(const char * presets
, std::string
& type
)
275 return parse_db_presets(presets
, 0, 0, &type
);
278 // Parse "USB: [DEVICE] ; [BRIDGE]" string
279 static void parse_usb_names(const char * names
, usb_dev_info
& info
)
281 int n1
= -1, n2
= -1, n3
= -1;
282 sscanf(names
, "USB: %n%*[^;]%n; %n", &n1
, &n2
, &n3
);
283 if (0 < n1
&& n1
< n2
)
284 info
.usb_device
.assign(names
+n1
, n2
-n1
);
286 sscanf(names
, "USB: ; %n", &n3
);
288 info
.usb_bridge
= names
+n3
;
291 // Search drivedb for USB device with vendor:product ID.
292 int lookup_usb_device(int vendor_id
, int product_id
, int bcd_device
,
293 usb_dev_info
& info
, usb_dev_info
& info2
)
295 // Format strings to match
296 char usb_id_str
[16], bcd_dev_str
[16];
297 snprintf(usb_id_str
, sizeof(usb_id_str
), "0x%04x:0x%04x", vendor_id
, product_id
);
299 snprintf(bcd_dev_str
, sizeof(bcd_dev_str
), "0x%04x", bcd_device
);
304 for (unsigned i
= 0; i
< knowndrives
.size(); i
++) {
305 const drive_settings
& dbentry
= knowndrives
[i
];
307 // Skip drive entries
308 if (get_dbentry_type(&dbentry
) != DBENTRY_USB
)
311 // Check whether USB vendor:product ID matches
312 if (!match(dbentry
.modelregexp
, usb_id_str
))
317 if (!parse_usb_type(dbentry
.presets
, d
.usb_type
))
318 return 0; // Syntax error
319 parse_usb_names(dbentry
.modelfamily
, d
);
321 // If two entries with same vendor:product ID have different
322 // types, use bcd_device (if provided by OS) to select entry.
323 if ( *dbentry
.firmwareregexp
&& *bcd_dev_str
324 && match(dbentry
.firmwareregexp
, bcd_dev_str
)) {
325 // Exact match including bcd_device
330 // First match without bcd_device
333 else if (info
.usb_type
!= d
.usb_type
) {
334 // Another possible match with different type
335 info2
= d
; found
= 2;
339 // Stop search at first matching entry with empty bcd_device
340 if (!*dbentry
.firmwareregexp
)
347 // Shows one entry of knowndrives[], returns #errors.
348 static int showonepreset(const drive_settings
* dbentry
)
352 && dbentry
->modelfamily
353 && dbentry
->modelregexp
&& *dbentry
->modelregexp
354 && dbentry
->firmwareregexp
355 && dbentry
->warningmsg
356 && dbentry
->presets
)) {
357 pout("Invalid drive database entry. Please report\n"
358 "this error to smartmontools developers at " PACKAGE_BUGREPORT
".\n");
362 dbentry_type type
= get_dbentry_type(dbentry
);
363 bool usb
= (type
== DBENTRY_USB
);
365 // print and check model and firmware regular expressions
367 regular_expression regex
;
368 pout("%-*s %s\n", TABLEPRINTWIDTH
, (!usb
? "MODEL REGEXP:" : "USB Vendor:Product:"),
369 dbentry
->modelregexp
);
370 if (!compile(regex
, dbentry
->modelregexp
))
373 pout("%-*s %s\n", TABLEPRINTWIDTH
, (!usb
? "FIRMWARE REGEXP:" : "USB bcdDevice:"),
374 *dbentry
->firmwareregexp
? dbentry
->firmwareregexp
: ".*"); // preserve old output (TODO: Change)
375 if (*dbentry
->firmwareregexp
&& !compile(regex
, dbentry
->firmwareregexp
))
379 pout("%-*s %s\n", TABLEPRINTWIDTH
, "MODEL FAMILY:", dbentry
->modelfamily
);
381 // if there are any presets, then show them
382 firmwarebug_defs firmwarebugs
;
383 bool first_preset
= true;
384 if (*dbentry
->presets
) {
385 ata_vendor_attr_defs defs
;
386 if (type
== DBENTRY_ATA_DEFAULT
) {
387 if (!parse_default_presets(dbentry
->presets
, defs
)) {
388 pout("Syntax error in DEFAULT option string \"%s\"\n", dbentry
->presets
);
393 if (!parse_presets(dbentry
->presets
, defs
, firmwarebugs
)) {
394 pout("Syntax error in preset option string \"%s\"\n", dbentry
->presets
);
399 for (int i
= 0; i
< MAX_ATTRIBUTE_NUM
; i
++) {
400 if (defs
[i
].priority
!= PRIOR_DEFAULT
|| !defs
[i
].name
.empty()) {
401 std::string name
= ata_get_smart_attr_name(i
, defs
);
402 // Use leading zeros instead of spaces so that everything lines up.
403 pout("%-*s %03d %s\n", TABLEPRINTWIDTH
, first_preset
? "ATTRIBUTE OPTIONS:" : "",
405 // Check max name length suitable for smartctl -A output
406 const unsigned maxlen
= 23;
407 if (name
.size() > maxlen
) {
408 pout("%*s\n", TABLEPRINTWIDTH
+6+maxlen
, "Error: Attribute name too long ------^");
411 first_preset
= false;
416 pout("%-*s %s\n", TABLEPRINTWIDTH
, "ATTRIBUTE OPTIONS:", "None preset; no -v options are required.");
418 // describe firmwarefix
419 for (int b
= BUG_NOLOGDIR
; b
<= BUG_XERRORLBA
; b
++) {
420 if (!firmwarebugs
.is_set((firmwarebug_t
)b
))
422 const char * fixdesc
;
423 switch ((firmwarebug_t
)b
) {
425 fixdesc
= "Avoids reading GP/SMART Log Directories (same as -F nologdir)";
428 fixdesc
= "Fixes byte order in some SMART data (same as -F samsung)";
431 fixdesc
= "Fixes byte order in some SMART data (same as -F samsung2)";
434 fixdesc
= "Fixes completed self-test reported as in progress (same as -F samsung3)";
437 fixdesc
= "Fixes LBA byte ordering in Ext. Comprehensive SMART error log (same as -F xerrorlba)";
440 fixdesc
= "UNKNOWN"; errcnt
++;
443 pout("%-*s %s\n", TABLEPRINTWIDTH
, "OTHER PRESETS:", fixdesc
);
448 usb_dev_info info
; parse_usb_names(dbentry
->modelfamily
, info
);
449 pout("%-*s %s\n", TABLEPRINTWIDTH
, "USB Device:",
450 (!info
.usb_device
.empty() ? info
.usb_device
.c_str() : "[unknown]"));
451 pout("%-*s %s\n", TABLEPRINTWIDTH
, "USB Bridge:",
452 (!info
.usb_bridge
.empty() ? info
.usb_bridge
.c_str() : "[unknown]"));
454 if (*dbentry
->presets
&& !parse_usb_type(dbentry
->presets
, info
.usb_type
)) {
455 pout("Syntax error in USB type string \"%s\"\n", dbentry
->presets
);
458 pout("%-*s %s\n", TABLEPRINTWIDTH
, "USB Type",
459 (!info
.usb_type
.empty() ? info
.usb_type
.c_str() : "[unsupported]"));
462 // Print any special warnings
463 if (*dbentry
->warningmsg
)
464 pout("%-*s %s\n", TABLEPRINTWIDTH
, "WARNINGS:", dbentry
->warningmsg
);
468 // Shows all presets for drives in knowndrives[].
469 // Returns #syntax errors.
472 // loop over all entries in the knowndrives[] table, printing them
473 // out in a nice format
475 for (unsigned i
= 0; i
< knowndrives
.size(); i
++) {
476 errcnt
+= showonepreset(&knowndrives
[i
]);
480 pout("Total number of entries :%5u\n"
481 "Entries read from file(s):%5u\n\n",
482 knowndrives
.size(), knowndrives
.custom_size());
484 pout("For information about adding a drive to the database see the FAQ on the\n");
485 pout("smartmontools home page: " PACKAGE_HOMEPAGE
"\n");
488 pout("\nFound %d syntax error(s) in database.\n"
489 "Please inform smartmontools developers at " PACKAGE_BUGREPORT
"\n", errcnt
);
493 // Shows all matching presets for a drive in knowndrives[].
494 // Returns # matching entries.
495 int showmatchingpresets(const char *model
, const char *firmware
)
498 const char * firmwaremsg
= (firmware
? firmware
: "(any)");
500 for (unsigned i
= 0; i
< knowndrives
.size(); i
++) {
501 if (!match(knowndrives
[i
].modelregexp
, model
))
503 if ( firmware
&& *knowndrives
[i
].firmwareregexp
504 && !match(knowndrives
[i
].firmwareregexp
, firmware
))
508 pout("Drive found in smartmontools Database. Drive identity strings:\n"
511 "match smartmontools Drive Database entry:\n",
512 TABLEPRINTWIDTH
, "MODEL:", model
, TABLEPRINTWIDTH
, "FIRMWARE:", firmwaremsg
);
514 pout("and match these additional entries:\n");
515 showonepreset(&knowndrives
[i
]);
519 pout("No presets are defined for this drive. Its identity strings:\n"
522 "do not match any of the known regular expressions.\n",
527 // Shows the presets (if any) that are available for the given drive.
528 void show_presets(const ata_identify_device
* drive
)
530 char model
[MODEL_STRING_LENGTH
+1], firmware
[FIRMWARE_STRING_LENGTH
+1];
532 // get the drive's model/firmware strings
533 ata_format_id_string(model
, drive
->model
, sizeof(model
)-1);
534 ata_format_id_string(firmware
, drive
->fw_rev
, sizeof(firmware
)-1);
536 // and search to see if they match values in the table
537 const drive_settings
* dbentry
= lookup_drive(model
, firmware
);
540 pout("No presets are defined for this drive. Its identity strings:\n"
543 "do not match any of the known regular expressions.\n"
544 "Use -P showall to list all known regular expressions.\n",
549 // We found a matching drive. Print out all information about it.
550 pout("Drive found in smartmontools Database. Drive identity strings:\n"
553 "match smartmontools Drive Database entry:\n",
554 TABLEPRINTWIDTH
, "MODEL:", model
, TABLEPRINTWIDTH
, "FIRMWARE:", firmware
);
555 showonepreset(dbentry
);
558 // Searches drive database and sets preset vendor attribute
559 // options in defs and firmwarebugs.
560 // Values that have already been set will not be changed.
561 // Returns pointer to database entry or nullptr if none found
562 const drive_settings
* lookup_drive_apply_presets(
563 const ata_identify_device
* drive
, ata_vendor_attr_defs
& defs
,
564 firmwarebug_defs
& firmwarebugs
)
566 // get the drive's model/firmware strings
567 char model
[MODEL_STRING_LENGTH
+1], firmware
[FIRMWARE_STRING_LENGTH
+1];
568 ata_format_id_string(model
, drive
->model
, sizeof(model
)-1);
569 ata_format_id_string(firmware
, drive
->fw_rev
, sizeof(firmware
)-1);
571 // Look up the drive in knowndrives[].
572 const drive_settings
* dbentry
= lookup_drive(model
, firmware
);
576 if (*dbentry
->presets
) {
578 if (!parse_presets(dbentry
->presets
, defs
, firmwarebugs
))
579 pout("Syntax error in preset option string \"%s\"\n", dbentry
->presets
);
585 /////////////////////////////////////////////////////////////////////////////
586 // Parser for drive database files
588 // Abstract pointer to read file input.
589 // Operations supported: c = *p; c = p[1]; ++p;
593 explicit stdin_iterator(FILE * f
)
594 : m_f(f
), m_next(0) { get(); get(); }
596 stdin_iterator
& operator++()
597 { get(); return *this; }
599 char operator*() const
602 char operator[](int i
) const
616 void stdin_iterator::get()
620 m_next
= (ch
!= EOF
? ch
: 0);
623 void stdin_iterator::fail() const
625 throw std::runtime_error("stdin_iterator: wrong usage");
629 // Use above as parser input 'pointer'. Can easily be changed later
630 // to e.g. 'const char *' if above is too slow.
631 typedef stdin_iterator parse_ptr
;
633 // Skip whitespace and comments.
634 static parse_ptr
skip_white(parse_ptr src
, const char * path
, int & line
)
636 for ( ; ; ++src
) switch (*src
) {
649 while (*src
&& *src
!= '\n')
655 // skip '/* comment */'
659 pout("%s(%d): Missing '*/'\n", path
, line
);
662 char c
= *src
; ++src
;
665 else if (c
== '*' && *src
== '/')
679 // Info about a token.
686 token_info() : type(0), line(0) { }
690 static parse_ptr
get_token(parse_ptr src
, token_info
& token
, const char * path
, int & line
)
692 src
= skip_white(src
, path
, line
);
694 case '{': case '}': case ',':
696 token
.type
= *src
; token
.line
= line
;
702 token
.type
= '"'; token
.line
= line
;
705 for (++src
; *src
!= '"'; ++src
) {
707 if (!c
|| c
== '\n' || (c
== '\\' && !src
[1])) {
708 pout("%s(%d): Missing terminating '\"'\n", path
, line
);
709 token
.type
= '?'; token
.line
= line
;
715 case 'n' : c
= '\n'; break;
716 case '\n': ++line
; break;
717 case '\\': case '"': break;
719 pout("%s(%d): Unknown escape sequence '\\%c'\n", path
, line
, c
);
720 token
.type
= '?'; token
.line
= line
;
726 // Lookahead to detect string constant concatentation
727 src
= skip_white(++src
, path
, line
);
728 } while (*src
== '"');
733 token
.type
= 0; token
.line
= line
;
737 pout("%s(%d): Syntax error, invalid char '%c'\n", path
, line
, *src
);
738 token
.type
= '?'; token
.line
= line
;
739 while (*src
&& *src
!= '\n')
747 // Parse drive database from abstract input pointer.
748 static bool parse_drive_database(parse_ptr src
, drive_database
& db
, const char * path
)
750 int state
= 0, field
= 0;
751 std::string values
[5];
754 token_info token
; int line
= 1;
755 src
= get_token(src
, token
, path
, line
);
757 // EOF is ok after '}', trailing ',' is also allowed.
758 if (!token
.type
&& (state
== 0 || state
== 4))
761 // Check expected token
762 const char expect
[] = "{\",},";
763 if (token
.type
!= expect
[state
]) {
764 if (token
.type
!= '?')
765 pout("%s(%d): Syntax error, '%c' expected\n", path
, token
.line
, expect
[state
]);
767 // Skip to next entry
768 while (token
.type
&& token
.type
!= '{')
769 src
= get_token(src
, token
, path
, line
);
776 // Interpret parser state
778 case 0: // ... ^{...}
779 state
= 1; field
= 0;
781 case 1: // {... ^"..." ...}
784 if (!token
.value
.empty()) {
785 regular_expression regex
;
786 if (!regex
.compile(token
.value
.c_str(), REG_EXTENDED
)) {
787 pout("%s(%d): Error in regular expression: %s\n", path
, token
.line
, regex
.get_errmsg());
791 else if (field
== 1) {
792 pout("%s(%d): Missing regular expression for drive model\n", path
, token
.line
);
797 if (!token
.value
.empty()) {
799 switch (get_modelfamily_type(values
[0].c_str())) {
800 case DBENTRY_ATA_DEFAULT
: {
801 ata_vendor_attr_defs defs
;
802 if (!parse_default_presets(token
.value
.c_str(), defs
)) {
803 pout("%s(%d): Syntax error in DEFAULT option string\n", path
, token
.line
);
807 default: { // DBENTRY_ATA
808 ata_vendor_attr_defs defs
; firmwarebug_defs fix
;
809 if (!parse_presets(token
.value
.c_str(), defs
, fix
)) {
810 pout("%s(%d): Syntax error in preset option string\n", path
, token
.line
);
816 if (!parse_usb_type(token
.value
.c_str(), type
)) {
817 pout("%s(%d): Syntax error in USB type string\n", path
, token
.line
);
825 values
[field
] = token
.value
;
826 state
= (++field
< 5 ? 2 : 3);
828 case 2: // {... "..."^, ...}
831 case 3: // {...^}, ...
833 drive_settings entry
;
834 entry
.modelfamily
= values
[0].c_str();
835 entry
.modelregexp
= values
[1].c_str();
836 entry
.firmwareregexp
= values
[2].c_str();
837 entry
.warningmsg
= values
[3].c_str();
838 entry
.presets
= values
[4].c_str();
843 case 4: // {...}^, ...
847 pout("Bad state %d\n", state
);
850 src
= get_token(src
, token
, path
, line
);
855 // Read drive database from file.
856 bool read_drive_database(const char * path
)
858 stdio_file
f(path
, "r"
859 #ifdef __CYGWIN__ // Allow files with '\r\n'.
864 pout("%s: cannot open drive database file\n", path
);
868 return parse_drive_database(parse_ptr(f
), knowndrives
, path
);
871 // Get path for additional database file
872 const char * get_drivedb_path_add()
875 return SMARTMONTOOLS_SYSCONFDIR
"/smart_drivedb.h";
877 static std::string path
= get_exe_dir() + "/drivedb-add.h";
882 #ifdef SMARTMONTOOLS_DRIVEDBDIR
884 // Get path for default database file
885 const char * get_drivedb_path_default()
888 return SMARTMONTOOLS_DRIVEDBDIR
"/drivedb.h";
890 static std::string path
= get_exe_dir() + "/drivedb.h";
897 // Read drive databases from standard places.
898 static bool read_default_drive_databases()
900 // Read file for local additions: /{,usr/local/}etc/smart_drivedb.h
901 const char * db1
= get_drivedb_path_add();
902 if (!access(db1
, 0)) {
903 if (!read_drive_database(db1
))
907 #ifdef SMARTMONTOOLS_DRIVEDBDIR
908 // Read file from package: /usr/{,local/}share/smartmontools/drivedb.h
909 const char * db2
= get_drivedb_path_default();
910 if (!access(db2
, 0)) {
911 if (!read_drive_database(db2
))
917 // Append builtin table.
918 knowndrives
.append(builtin_knowndrives
, builtin_knowndrives_size
);
924 static ata_vendor_attr_defs default_attr_defs
;
926 // Initialize default_attr_defs.
927 static bool init_default_attr_defs()
929 // Lookup default entry
930 const drive_settings
* entry
= 0;
931 for (unsigned i
= 0; i
< knowndrives
.size(); i
++) {
932 if (get_dbentry_type(&knowndrives
[i
]) != DBENTRY_ATA_DEFAULT
)
934 entry
= &knowndrives
[i
];
939 // Fall back to builtin database
940 for (unsigned i
= 0; i
< builtin_knowndrives_size
; i
++) {
941 if (get_dbentry_type(&builtin_knowndrives
[i
]) != DBENTRY_ATA_DEFAULT
)
943 entry
= &builtin_knowndrives
[i
];
948 throw std::logic_error("DEFAULT entry missing in builtin drive database");
950 pout("Warning: DEFAULT entry missing in drive database file(s)\n");
953 if (!parse_default_presets(entry
->presets
, default_attr_defs
)) {
954 pout("Syntax error in DEFAULT drive database entry\n");
961 // Init default db entry and optionally read drive databases from standard places.
962 bool init_drive_database(bool use_default_db
)
964 if (use_default_db
&& !read_default_drive_databases())
967 return init_default_attr_defs();
970 // Get vendor attribute options from default db entry.
971 const ata_vendor_attr_defs
& get_default_attr_defs()
973 return default_attr_defs
;