aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-core.c
diff options
context:
space:
mode:
authorMark Lord <kernel@teksavvy.com>2010-07-01 18:16:14 -0400
committerJeff Garzik <jgarzik@redhat.com>2010-08-01 19:36:03 -0400
commitbce036cea10a8dd21eb8c9bf1b641d8790429c8e (patch)
tree2e0d87245467b30fced2d65e7cfe9352ee930f2c /drivers/ata/libata-core.c
parentda10a2002cf25a11f18fa1b5e327b9ed717f819c (diff)
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 <mlord@pobox.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata/libata-core.c')
-rw-r--r--drivers/ata/libata-core.c78
1 files changed, 57 insertions, 21 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index ddf8e4862787..f8c72a1867fd 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4326,29 +4326,65 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
4326 { } 4326 { }
4327}; 4327};
4328 4328
4329static 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 */
4354static int glob_match (const char *text, const char *pattern)
4330{ 4355{
4331 const char *p; 4356 do {
4332 int len; 4357 /* Match single character or a '?' wildcard */
4333 4358 if (*text == *pattern || *pattern == '?') {
4334 /* 4359 if (!*pattern++)
4335 * check for trailing wildcard: *\0 4360 return 0; /* End of both strings: match */
4336 */ 4361 } else {
4337 p = strchr(patt, wildchar); 4362 /* Match single char against a '[' bracketed ']' pattern set */
4338 if (p && ((*(p + 1)) == 0)) 4363 if (!*text || *pattern != '[')
4339 len = p - patt; 4364 break; /* Not a pattern set */
4340 else { 4365 while (*++pattern && *pattern != ']' && *text != *pattern);
4341 len = strlen(name); 4366 if (!*pattern || *pattern == ']')
4342 if (!len) { 4367 return 1; /* No match */
4343 if (!*patt) 4368 while (*pattern && *pattern++ != ']');
4344 return 0; 4369 }
4345 return -1; 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 */
4346 } 4381 }
4347 } 4382 }
4348 4383 if (!*text && !*pattern)
4349 return strncmp(patt, name, len); 4384 return 0; /* End of both strings: match */
4385 return 1; /* No match */
4350} 4386}
4351 4387
4352static unsigned long ata_dev_blacklisted(const struct ata_device *dev) 4388static unsigned long ata_dev_blacklisted(const struct ata_device *dev)
4353{ 4389{
4354 unsigned char model_num[ATA_ID_PROD_LEN + 1]; 4390 unsigned char model_num[ATA_ID_PROD_LEN + 1];
@@ -4359,10 +4395,10 @@ static unsigned long ata_dev_blacklisted(const struct ata_device *dev)
4359 ata_id_c_string(dev->id, model_rev, ATA_ID_FW_REV, sizeof(model_rev)); 4395 ata_id_c_string(dev->id, model_rev, ATA_ID_FW_REV, sizeof(model_rev));
4360 4396
4361 while (ad->model_num) { 4397 while (ad->model_num) {
4362 if (!strn_pattern_cmp(ad->model_num, model_num, '*')) { 4398 if (!glob_match(model_num, ad->model_num)) {
4363 if (ad->model_rev == NULL) 4399 if (ad->model_rev == NULL)
4364 return ad->horkage; 4400 return ad->horkage;
4365 if (!strn_pattern_cmp(ad->model_rev, model_rev, '*')) 4401 if (!glob_match(model_rev, ad->model_rev))
4366 return ad->horkage; 4402 return ad->horkage;
4367 } 4403 }
4368 ad++; 4404 ad++;