31#define MODEL_STRING_LENGTH 40
32#define FIRMWARE_STRING_LENGTH 8
33#define TABLEPRINTWIDTH 19
91: m_builtin_tab(0), m_builtin_size(0)
120 size_t len = strlen(src);
121 char * dest =
new char[len+1];
122 memcpy(dest, src, len+1);
127 delete [] dest;
throw;
149 else if (modelfamily[0] ==
'D' && !strcmp(modelfamily,
"DEFAULT"))
151 else if (modelfamily[0] ==
'U' &&
str_starts_with(modelfamily,
"USB:"))
166 "^VERSION: ([0-9]+\\.[0-9]+)(/([0-9]+) | \\$[^0-9]* ([0-9]+) )"
169 const int nmatch = 1+4;
173 dbversion.assign(verstr +
match[1].rm_so,
match[1].rm_eo -
match[1].rm_so);
174 int i = (
match[3].rm_so >= 0 ? 3 : 4);
176 dbversion.append(verstr +
match[i].rm_so,
match[i].rm_eo -
match[i].rm_so);
183 pout(
"Internal error: unable to compile regular expression \"%s\": %s\n"
184 "Please inform smartmontools developers at " PACKAGE_BUGREPORT
"\n",
192static bool match(
const char * pattern,
const char * str)
205 std::string * dbversion =
nullptr)
247 for (
int i = 0; ; ) {
248 i += strspn(presets+i,
" \t");
251 char opt, arg[80+1+13];
int len = -1;
252 if (!(sscanf(presets+i,
"-%c %80[^ ]%n", &opt, arg, &len) >= 2 && len > 0))
254 if (opt ==
'v' && defs) {
259 else if (opt ==
'F' && firmwarebugs) {
265 firmwarebugs->
set(bug);
267 else if (opt ==
'd' && type) {
303 int n1 = -1, n2 = -1, n3 = -1;
304 sscanf(names,
"USB: %n%*[^;]%n; %n", &n1, &n2, &n3);
305 if (0 < n1 && n1 < n2)
308 sscanf(names,
"USB: ; %n", &n3);
318 char usb_id_str[16], bcd_dev_str[16];
319 snprintf(usb_id_str,
sizeof(usb_id_str),
"0x%04x:0x%04x", vendor_id, product_id);
321 snprintf(bcd_dev_str,
sizeof(bcd_dev_str),
"0x%04x", bcd_device);
357 info2 = d; found = 2;
379 pout(
"Invalid drive database entry. Please report\n"
380 "this error to smartmontools developers at " PACKAGE_BUGREPORT
".\n");
405 bool first_preset =
true;
410 pout(
"Syntax error in DEFAULT option string \"%s\"\n", dbentry->
presets);
416 pout(
"Syntax error in preset option string \"%s\"\n", dbentry->
presets);
422 if (defs[i].priority !=
PRIOR_DEFAULT || !defs[i].name.empty()) {
428 const unsigned maxlen = 23;
429 if (name.size() > maxlen) {
433 first_preset =
false;
438 pout(
"%-*s %s\n",
TABLEPRINTWIDTH,
"ATTRIBUTE OPTIONS:",
"None preset; no -v options are required.");
444 const char * fixdesc;
447 fixdesc =
"Avoids reading GP/SMART Log Directories (same as -F nologdir)";
450 fixdesc =
"Fixes byte order in some SMART data (same as -F samsung)";
453 fixdesc =
"Fixes byte order in some SMART data (same as -F samsung2)";
456 fixdesc =
"Fixes completed self-test reported as in progress (same as -F samsung3)";
459 fixdesc =
"Fixes LBA byte ordering in Ext. Comprehensive SMART error log (same as -F xerrorlba)";
462 fixdesc =
"UNKNOWN"; errcnt++;
477 pout(
"Syntax error in USB type string \"%s\"\n", dbentry->
presets);
502 pout(
"Total number of entries :%5u\n"
503 "Entries read from file(s):%5u\n\n",
506 pout(
"For information about adding a drive to the database see the FAQ on the\n");
507 pout(
"smartmontools home page: " PACKAGE_URL
"\n");
510 pout(
"\nFound %d syntax error(s) in database.\n"
511 "Please inform smartmontools developers at " PACKAGE_BUGREPORT
"\n", errcnt);
520 const char * firmwaremsg = (firmware ? firmware :
"(any)");
530 pout(
"Drive found in smartmontools Database. Drive identity strings:\n"
533 "match smartmontools Drive Database entry:\n",
536 pout(
"and match these additional entries:\n");
541 pout(
"No presets are defined for this drive. Its identity strings:\n"
544 "do not match any of the known regular expressions.\n",
562 pout(
"No presets are defined for this drive. Its identity strings:\n"
565 "do not match any of the known regular expressions.\n"
566 "Use -P showall to list all known regular expressions.\n",
572 pout(
"Drive found in smartmontools Database. Drive identity strings:\n"
575 "match smartmontools Drive Database entry:\n",
601 pout(
"Syntax error in preset option string \"%s\"\n", dbentry->
presets);
619 {
get();
return *
this; }
642 m_next = (ch != EOF ? ch : 0);
647 throw std::runtime_error(
"stdin_iterator: wrong usage");
658 for ( ; ; ++src)
switch (*src) {
671 while (*src && *src !=
'\n')
681 pout(
"%s(%d): Missing '*/'\n", path, line);
684 char c = *src; ++src;
687 else if (c ==
'*' && *src ==
'/')
716 case '{':
case '}':
case ',':
718 token.
type = *src; token.
line = line;
724 token.
type =
'"'; token.
line = line;
727 for (++src; *src !=
'"'; ++src) {
729 if (!c || c ==
'\n' || (c ==
'\\' && !src[1])) {
730 pout(
"%s(%d): Missing terminating '\"'\n", path, line);
731 token.
type =
'?'; token.
line = line;
737 case 'n' : c =
'\n';
break;
738 case '\n': ++line;
break;
739 case '\\':
case '"':
break;
741 pout(
"%s(%d): Unknown escape sequence '\\%c'\n", path, line, c);
742 token.
type =
'?'; token.
line = line;
750 }
while (*src ==
'"');
759 pout(
"%s(%d): Syntax error, invalid char '%c'\n", path, line, *src);
760 token.
type =
'?'; token.
line = line;
761 while (*src && *src !=
'\n')
772 int state = 0, field = 0;
773 std::string values[5];
780 if (!token.
type && (state == 0 || state == 4))
784 const char expect[] =
"{\",},";
785 if (token.
type != expect[state]) {
786 if (token.
type !=
'?')
787 pout(
"%s(%d): Syntax error, '%c' expected\n", path, token.
line, expect[state]);
790 while (token.
type && token.
type !=
'{')
801 state = 1; field = 0;
806 if (!token.
value.empty()) {
809 pout(
"%s(%d): Error in regular expression: %s\n", path, token.
line, regex.
get_errmsg());
813 else if (field == 1) {
814 pout(
"%s(%d): Missing regular expression for drive model\n", path, token.
line);
819 if (!token.
value.empty()) {
825 pout(
"%s(%d): Syntax error in DEFAULT option string\n", path, token.
line);
832 pout(
"%s(%d): Syntax error in preset option string\n", path, token.
line);
839 pout(
"%s(%d): Syntax error in USB type string\n", path, token.
line);
847 values[field] = token.
value;
848 state = (++field < 5 ? 2 : 3);
856 entry.modelfamily = values[0].c_str();
857 entry.modelregexp = values[1].c_str();
858 entry.firmwareregexp = values[2].c_str();
859 entry.warningmsg = values[3].c_str();
860 entry.presets = values[4].c_str();
869 pout(
"Bad state %d\n", state);
886 pout(
"%s: cannot open drive database file\n", path);
897 return SMARTMONTOOLS_SYSCONFDIR
"/smart_drivedb.h";
899 static std::string path =
get_exe_dir() +
"/drivedb-add.h";
904#ifdef SMARTMONTOOLS_DRIVEDBDIR
907const char * get_drivedb_path_default()
910 return SMARTMONTOOLS_DRIVEDBDIR
"/drivedb.h";
912 static std::string path =
get_exe_dir() +
"/drivedb.h";
924 if (!access(db1, 0)) {
929#ifdef SMARTMONTOOLS_DRIVEDBDIR
931 const char * db2 = get_drivedb_path_default();
932 if (!access(db2, 0)) {
970 throw std::logic_error(
"DEFAULT entry missing in builtin drive database");
972 pout(
"Warning: DEFAULT entry missing in drive database file(s)\n");
976 pout(
"Syntax error in DEFAULT drive database entry\n");
bool parse_attribute_def(const char *opt, ata_vendor_attr_defs &defs, ata_vendor_def_prior priority)
bool parse_firmwarebug_def(const char *opt, firmwarebug_defs &firmwarebugs)
std::string ata_get_smart_attr_name(unsigned char id, const ata_vendor_attr_defs &defs, int rpm)
void ata_format_id_string(char *out, const unsigned char *in, int n)
#define MAX_ATTRIBUTE_NUM
const char * copy_string(const char *str)
unsigned size() const
Get total number of entries.
void push_back(const drive_settings &src)
Append new custom entry.
unsigned custom_size() const
Get number of custom entries.
const drive_settings * m_builtin_tab
std::vector< char * > m_custom_strings
void append(const drive_settings *builtin_tab, unsigned builtin_size)
Append builtin table.
drive_database(const drive_database &)
void operator=(const drive_database &)
std::vector< drive_settings > m_custom_tab
const drive_settings & operator[](unsigned i)
Array access.
void set(firmwarebug_t bug)
bool is_set(firmwarebug_t bug) const
Wrapper class for POSIX regex(3) or std::regex Supports copy & assignment and is compatible with STL ...
bool full_match(const char *str) const
Return true if full string matches pattern.
const char * get_errmsg() const
Get error message from last compile().
bool compile(const char *pattern)
Set and compile new pattern, return false on error.
bool execute(const char *str, unsigned nmatch, match_range *pmatch) const
Return true if substring matches pattern, fill match_range array.
stdin_iterator & operator++()
char operator[](int i) const
Wrapper class for FILE *.
const drive_settings * lookup_drive_apply_presets(const ata_identify_device *drive, ata_vendor_attr_defs &defs, firmwarebug_defs &firmwarebugs, std::string &dbversion)
static bool parse_presets(const char *presets, ata_vendor_attr_defs &defs, firmwarebug_defs &firmwarebugs)
bool init_drive_database(bool use_default_db)
const drive_settings builtin_knowndrives[]
const char * get_drivedb_path_add()
static bool match(const char *pattern, const char *str)
static const drive_settings * lookup_drive(const char *model, const char *firmware, std::string *dbversion=nullptr)
static bool parse_db_presets(const char *presets, ata_vendor_attr_defs *defs, firmwarebug_defs *firmwarebugs, std::string *type)
static dbentry_type get_dbentry_type(const drive_settings *dbentry)
void show_presets(const ata_identify_device *drive)
bool read_drive_database(const char *path)
static bool parse_drive_database(parse_ptr src, drive_database &db, const char *path)
#define FIRMWARE_STRING_LENGTH
const char * knowndrives_cpp_cvsid
static parse_ptr get_token(parse_ptr src, token_info &token, const char *path, int &line)
const unsigned builtin_knowndrives_size
static int showonepreset(const drive_settings *dbentry)
static void parse_version(std::string &dbversion, const char *verstr)
static bool init_default_attr_defs()
static void parse_usb_names(const char *names, usb_dev_info &info)
static drive_database knowndrives
The drive database.
static bool parse_usb_type(const char *presets, std::string &type)
int lookup_usb_device(int vendor_id, int product_id, int bcd_device, usb_dev_info &info, usb_dev_info &info2)
static bool read_default_drive_databases()
static parse_ptr skip_white(parse_ptr src, const char *path, int &line)
const ata_vendor_attr_defs & get_default_attr_defs()
static bool compile(regular_expression ®ex, const char *pattern)
static bool parse_default_presets(const char *presets, ata_vendor_attr_defs &defs)
int showmatchingpresets(const char *model, const char *firmware)
#define MODEL_STRING_LENGTH
static ata_vendor_attr_defs default_attr_defs
static dbentry_type get_modelfamily_type(const char *modelfamily)
#define KNOWNDRIVES_H_CVSID
std::string get_exe_dir()
void pout(const char *fmt,...)
const char * firmwareregexp
bool str_starts_with(const char *str, const char *prefix)