@@ -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+
43524388static 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