Skip to content

Commit bce036c

Browse files
Mark LordJeff Garzik
authored andcommitted
libata: glob_match for ata_device_blacklist (v2)
Replace rudimentry pattern matching with more capable shell-style globbing. This will enable shrinking ata_device_blacklist[] table in subsequent patches, and helps with future editions to the table, such as matching only the end of a firmware revision string etc.. Signed-off-by: Mark Lord <[email protected]> Signed-off-by: Jeff Garzik <[email protected]>
1 parent da10a20 commit bce036c

File tree

1 file changed

+57
-21
lines changed

1 file changed

+57
-21
lines changed

drivers/ata/libata-core.c

Lines changed: 57 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4326,29 +4326,65 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
43264326
{ }
43274327
};
43284328

4329-
static int strn_pattern_cmp(const char *patt, const char *name, int wildchar)
4329+
/**
4330+
* glob_match - match a text string against a glob-style pattern
4331+
* @text: the string to be examined
4332+
* @pattern: the glob-style pattern to be matched against
4333+
*
4334+
* Either/both of text and pattern can be empty strings.
4335+
*
4336+
* Match text against a glob-style pattern, with wildcards and simple sets:
4337+
*
4338+
* ? matches any single character.
4339+
* * matches any run of characters.
4340+
* [xyz] matches a single character from the set: x, y, or z.
4341+
*
4342+
* Note: hyphenated ranges [0-9] are _not_ supported here.
4343+
* The special characters ?, [, or *, can be matched using a set, eg. [*]
4344+
*
4345+
* Example patterns: "SD1?", "SD1[012345]", "*R0", SD*1?[012]*xx"
4346+
*
4347+
* This function uses one level of recursion per '*' in pattern.
4348+
* Since it calls _nothing_ else, and has _no_ explicit local variables,
4349+
* this will not cause stack problems for any reasonable use here.
4350+
*
4351+
* RETURNS:
4352+
* 0 on match, 1 otherwise.
4353+
*/
4354+
static int glob_match (const char *text, const char *pattern)
43304355
{
4331-
const char *p;
4332-
int len;
4333-
4334-
/*
4335-
* check for trailing wildcard: *\0
4336-
*/
4337-
p = strchr(patt, wildchar);
4338-
if (p && ((*(p + 1)) == 0))
4339-
len = p - patt;
4340-
else {
4341-
len = strlen(name);
4342-
if (!len) {
4343-
if (!*patt)
4344-
return 0;
4345-
return -1;
4356+
do {
4357+
/* Match single character or a '?' wildcard */
4358+
if (*text == *pattern || *pattern == '?') {
4359+
if (!*pattern++)
4360+
return 0; /* End of both strings: match */
4361+
} else {
4362+
/* Match single char against a '[' bracketed ']' pattern set */
4363+
if (!*text || *pattern != '[')
4364+
break; /* Not a pattern set */
4365+
while (*++pattern && *pattern != ']' && *text != *pattern);
4366+
if (!*pattern || *pattern == ']')
4367+
return 1; /* No match */
4368+
while (*pattern && *pattern++ != ']');
4369+
}
4370+
} while (*++text && *pattern);
4371+
4372+
/* Match any run of chars against a '*' wildcard */
4373+
if (*pattern == '*') {
4374+
if (!*++pattern)
4375+
return 0; /* Match: avoid recursion at end of pattern */
4376+
/* Loop to handle additional pattern chars after the wildcard */
4377+
while (*text) {
4378+
if (glob_match(text, pattern) == 0)
4379+
return 0; /* Remainder matched */
4380+
++text; /* Absorb (match) this char and try again */
43464381
}
43474382
}
4348-
4349-
return strncmp(patt, name, len);
4383+
if (!*text && !*pattern)
4384+
return 0; /* End of both strings: match */
4385+
return 1; /* No match */
43504386
}
4351-
4387+
43524388
static unsigned long ata_dev_blacklisted(const struct ata_device *dev)
43534389
{
43544390
unsigned char model_num[ATA_ID_PROD_LEN + 1];
@@ -4359,10 +4395,10 @@ static unsigned long ata_dev_blacklisted(const struct ata_device *dev)
43594395
ata_id_c_string(dev->id, model_rev, ATA_ID_FW_REV, sizeof(model_rev));
43604396

43614397
while (ad->model_num) {
4362-
if (!strn_pattern_cmp(ad->model_num, model_num, '*')) {
4398+
if (!glob_match(model_num, ad->model_num)) {
43634399
if (ad->model_rev == NULL)
43644400
return ad->horkage;
4365-
if (!strn_pattern_cmp(ad->model_rev, model_rev, '*'))
4401+
if (!glob_match(model_rev, ad->model_rev))
43664402
return ad->horkage;
43674403
}
43684404
ad++;

0 commit comments

Comments
 (0)