Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bce036ce authored by Mark Lord's avatar Mark Lord Committed by Jeff Garzik
Browse files

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: default avatarMark Lord <mlord@pobox.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent da10a200
Loading
Loading
Loading
Loading
+57 −21
Original line number Diff line number Diff line
@@ -4326,27 +4326,63 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
	{ }
};

static int strn_pattern_cmp(const char *patt, const char *name, int wildchar)
/**
 *	glob_match - match a text string against a glob-style pattern
 *	@text: the string to be examined
 *	@pattern: the glob-style pattern to be matched against
 *
 *	Either/both of text and pattern can be empty strings.
 *
 *	Match text against a glob-style pattern, with wildcards and simple sets:
 *
 *		?	matches any single character.
 *		*	matches any run of characters.
 *		[xyz]	matches a single character from the set: x, y, or z.
 *
 *	Note: hyphenated ranges [0-9] are _not_ supported here.
 *	The special characters ?, [, or *, can be matched using a set, eg. [*]
 *
 *	Example patterns:  "SD1?",  "SD1[012345]",  "*R0",  SD*1?[012]*xx"
 *
 *	This function uses one level of recursion per '*' in pattern.
 *	Since it calls _nothing_ else, and has _no_ explicit local variables,
 *	this will not cause stack problems for any reasonable use here.
 *
 *	RETURNS:
 *	0 on match, 1 otherwise.
 */
static int glob_match (const char *text, const char *pattern)
{
	const char *p;
	int len;
	do {
		/* Match single character or a '?' wildcard */
		if (*text == *pattern || *pattern == '?') {
			if (!*pattern++)
				return 0;  /* End of both strings: match */
		} else {
			/* Match single char against a '[' bracketed ']' pattern set */
			if (!*text || *pattern != '[')
				break;  /* Not a pattern set */
			while (*++pattern && *pattern != ']' && *text != *pattern);
			if (!*pattern || *pattern == ']')
				return 1;  /* No match */
			while (*pattern && *pattern++ != ']');
		}
	} while (*++text && *pattern);

	/*
	 * check for trailing wildcard: *\0
	 */
	p = strchr(patt, wildchar);
	if (p && ((*(p + 1)) == 0))
		len = p - patt;
	else {
		len = strlen(name);
		if (!len) {
			if (!*patt)
				return 0;
			return -1;
	/* Match any run of chars against a '*' wildcard */
	if (*pattern == '*') {
		if (!*++pattern)
			return 0;  /* Match: avoid recursion at end of pattern */
		/* Loop to handle additional pattern chars after the wildcard */
		while (*text) {
			if (glob_match(text, pattern) == 0)
				return 0;  /* Remainder matched */
			++text;  /* Absorb (match) this char and try again */
		}
	}

	return strncmp(patt, name, len);
	if (!*text && !*pattern)
		return 0;  /* End of both strings: match */
	return 1;  /* No match */
}
 
static unsigned long ata_dev_blacklisted(const struct ata_device *dev)
@@ -4359,10 +4395,10 @@ static unsigned long ata_dev_blacklisted(const struct ata_device *dev)
	ata_id_c_string(dev->id, model_rev, ATA_ID_FW_REV, sizeof(model_rev));

	while (ad->model_num) {
		if (!strn_pattern_cmp(ad->model_num, model_num, '*')) {
		if (!glob_match(model_num, ad->model_num)) {
			if (ad->model_rev == NULL)
				return ad->horkage;
			if (!strn_pattern_cmp(ad->model_rev, model_rev, '*'))
			if (!glob_match(model_rev, ad->model_rev))
				return ad->horkage;
		}
		ad++;