18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Extracted fronm glob.c
38c2ecf20Sopenharmony_ci */
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#include <linux/module.h>
68c2ecf20Sopenharmony_ci#include <linux/moduleparam.h>
78c2ecf20Sopenharmony_ci#include <linux/glob.h>
88c2ecf20Sopenharmony_ci#include <linux/printk.h>
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci/* Boot with "glob.verbose=1" to show successful tests, too */
118c2ecf20Sopenharmony_cistatic bool verbose = false;
128c2ecf20Sopenharmony_cimodule_param(verbose, bool, 0);
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_cistruct glob_test {
158c2ecf20Sopenharmony_ci	char const *pat, *str;
168c2ecf20Sopenharmony_ci	bool expected;
178c2ecf20Sopenharmony_ci};
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_cistatic bool __pure __init test(char const *pat, char const *str, bool expected)
208c2ecf20Sopenharmony_ci{
218c2ecf20Sopenharmony_ci	bool match = glob_match(pat, str);
228c2ecf20Sopenharmony_ci	bool success = match == expected;
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci	/* Can't get string literals into a particular section, so... */
258c2ecf20Sopenharmony_ci	static char const msg_error[] __initconst =
268c2ecf20Sopenharmony_ci		KERN_ERR "glob: \"%s\" vs. \"%s\": %s *** ERROR ***\n";
278c2ecf20Sopenharmony_ci	static char const msg_ok[] __initconst =
288c2ecf20Sopenharmony_ci		KERN_DEBUG "glob: \"%s\" vs. \"%s\": %s OK\n";
298c2ecf20Sopenharmony_ci	static char const mismatch[] __initconst = "mismatch";
308c2ecf20Sopenharmony_ci	char const *message;
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci	if (!success)
338c2ecf20Sopenharmony_ci		message = msg_error;
348c2ecf20Sopenharmony_ci	else if (verbose)
358c2ecf20Sopenharmony_ci		message = msg_ok;
368c2ecf20Sopenharmony_ci	else
378c2ecf20Sopenharmony_ci		return success;
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci	printk(message, pat, str, mismatch + 3*match);
408c2ecf20Sopenharmony_ci	return success;
418c2ecf20Sopenharmony_ci}
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci/*
448c2ecf20Sopenharmony_ci * The tests are all jammed together in one array to make it simpler
458c2ecf20Sopenharmony_ci * to place that array in the .init.rodata section.  The obvious
468c2ecf20Sopenharmony_ci * "array of structures containing char *" has no way to force the
478c2ecf20Sopenharmony_ci * pointed-to strings to be in a particular section.
488c2ecf20Sopenharmony_ci *
498c2ecf20Sopenharmony_ci * Anyway, a test consists of:
508c2ecf20Sopenharmony_ci * 1. Expected glob_match result: '1' or '0'.
518c2ecf20Sopenharmony_ci * 2. Pattern to match: null-terminated string
528c2ecf20Sopenharmony_ci * 3. String to match against: null-terminated string
538c2ecf20Sopenharmony_ci *
548c2ecf20Sopenharmony_ci * The list of tests is terminated with a final '\0' instead of
558c2ecf20Sopenharmony_ci * a glob_match result character.
568c2ecf20Sopenharmony_ci */
578c2ecf20Sopenharmony_cistatic char const glob_tests[] __initconst =
588c2ecf20Sopenharmony_ci	/* Some basic tests */
598c2ecf20Sopenharmony_ci	"1" "a\0" "a\0"
608c2ecf20Sopenharmony_ci	"0" "a\0" "b\0"
618c2ecf20Sopenharmony_ci	"0" "a\0" "aa\0"
628c2ecf20Sopenharmony_ci	"0" "a\0" "\0"
638c2ecf20Sopenharmony_ci	"1" "\0" "\0"
648c2ecf20Sopenharmony_ci	"0" "\0" "a\0"
658c2ecf20Sopenharmony_ci	/* Simple character class tests */
668c2ecf20Sopenharmony_ci	"1" "[a]\0" "a\0"
678c2ecf20Sopenharmony_ci	"0" "[a]\0" "b\0"
688c2ecf20Sopenharmony_ci	"0" "[!a]\0" "a\0"
698c2ecf20Sopenharmony_ci	"1" "[!a]\0" "b\0"
708c2ecf20Sopenharmony_ci	"1" "[ab]\0" "a\0"
718c2ecf20Sopenharmony_ci	"1" "[ab]\0" "b\0"
728c2ecf20Sopenharmony_ci	"0" "[ab]\0" "c\0"
738c2ecf20Sopenharmony_ci	"1" "[!ab]\0" "c\0"
748c2ecf20Sopenharmony_ci	"1" "[a-c]\0" "b\0"
758c2ecf20Sopenharmony_ci	"0" "[a-c]\0" "d\0"
768c2ecf20Sopenharmony_ci	/* Corner cases in character class parsing */
778c2ecf20Sopenharmony_ci	"1" "[a-c-e-g]\0" "-\0"
788c2ecf20Sopenharmony_ci	"0" "[a-c-e-g]\0" "d\0"
798c2ecf20Sopenharmony_ci	"1" "[a-c-e-g]\0" "f\0"
808c2ecf20Sopenharmony_ci	"1" "[]a-ceg-ik[]\0" "a\0"
818c2ecf20Sopenharmony_ci	"1" "[]a-ceg-ik[]\0" "]\0"
828c2ecf20Sopenharmony_ci	"1" "[]a-ceg-ik[]\0" "[\0"
838c2ecf20Sopenharmony_ci	"1" "[]a-ceg-ik[]\0" "h\0"
848c2ecf20Sopenharmony_ci	"0" "[]a-ceg-ik[]\0" "f\0"
858c2ecf20Sopenharmony_ci	"0" "[!]a-ceg-ik[]\0" "h\0"
868c2ecf20Sopenharmony_ci	"0" "[!]a-ceg-ik[]\0" "]\0"
878c2ecf20Sopenharmony_ci	"1" "[!]a-ceg-ik[]\0" "f\0"
888c2ecf20Sopenharmony_ci	/* Simple wild cards */
898c2ecf20Sopenharmony_ci	"1" "?\0" "a\0"
908c2ecf20Sopenharmony_ci	"0" "?\0" "aa\0"
918c2ecf20Sopenharmony_ci	"0" "??\0" "a\0"
928c2ecf20Sopenharmony_ci	"1" "?x?\0" "axb\0"
938c2ecf20Sopenharmony_ci	"0" "?x?\0" "abx\0"
948c2ecf20Sopenharmony_ci	"0" "?x?\0" "xab\0"
958c2ecf20Sopenharmony_ci	/* Asterisk wild cards (backtracking) */
968c2ecf20Sopenharmony_ci	"0" "*??\0" "a\0"
978c2ecf20Sopenharmony_ci	"1" "*??\0" "ab\0"
988c2ecf20Sopenharmony_ci	"1" "*??\0" "abc\0"
998c2ecf20Sopenharmony_ci	"1" "*??\0" "abcd\0"
1008c2ecf20Sopenharmony_ci	"0" "??*\0" "a\0"
1018c2ecf20Sopenharmony_ci	"1" "??*\0" "ab\0"
1028c2ecf20Sopenharmony_ci	"1" "??*\0" "abc\0"
1038c2ecf20Sopenharmony_ci	"1" "??*\0" "abcd\0"
1048c2ecf20Sopenharmony_ci	"0" "?*?\0" "a\0"
1058c2ecf20Sopenharmony_ci	"1" "?*?\0" "ab\0"
1068c2ecf20Sopenharmony_ci	"1" "?*?\0" "abc\0"
1078c2ecf20Sopenharmony_ci	"1" "?*?\0" "abcd\0"
1088c2ecf20Sopenharmony_ci	"1" "*b\0" "b\0"
1098c2ecf20Sopenharmony_ci	"1" "*b\0" "ab\0"
1108c2ecf20Sopenharmony_ci	"0" "*b\0" "ba\0"
1118c2ecf20Sopenharmony_ci	"1" "*b\0" "bb\0"
1128c2ecf20Sopenharmony_ci	"1" "*b\0" "abb\0"
1138c2ecf20Sopenharmony_ci	"1" "*b\0" "bab\0"
1148c2ecf20Sopenharmony_ci	"1" "*bc\0" "abbc\0"
1158c2ecf20Sopenharmony_ci	"1" "*bc\0" "bc\0"
1168c2ecf20Sopenharmony_ci	"1" "*bc\0" "bbc\0"
1178c2ecf20Sopenharmony_ci	"1" "*bc\0" "bcbc\0"
1188c2ecf20Sopenharmony_ci	/* Multiple asterisks (complex backtracking) */
1198c2ecf20Sopenharmony_ci	"1" "*ac*\0" "abacadaeafag\0"
1208c2ecf20Sopenharmony_ci	"1" "*ac*ae*ag*\0" "abacadaeafag\0"
1218c2ecf20Sopenharmony_ci	"1" "*a*b*[bc]*[ef]*g*\0" "abacadaeafag\0"
1228c2ecf20Sopenharmony_ci	"0" "*a*b*[ef]*[cd]*g*\0" "abacadaeafag\0"
1238c2ecf20Sopenharmony_ci	"1" "*abcd*\0" "abcabcabcabcdefg\0"
1248c2ecf20Sopenharmony_ci	"1" "*ab*cd*\0" "abcabcabcabcdefg\0"
1258c2ecf20Sopenharmony_ci	"1" "*abcd*abcdef*\0" "abcabcdabcdeabcdefg\0"
1268c2ecf20Sopenharmony_ci	"0" "*abcd*\0" "abcabcabcabcefg\0"
1278c2ecf20Sopenharmony_ci	"0" "*ab*cd*\0" "abcabcabcabcefg\0";
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_cistatic int __init glob_init(void)
1308c2ecf20Sopenharmony_ci{
1318c2ecf20Sopenharmony_ci	unsigned successes = 0;
1328c2ecf20Sopenharmony_ci	unsigned n = 0;
1338c2ecf20Sopenharmony_ci	char const *p = glob_tests;
1348c2ecf20Sopenharmony_ci	static char const message[] __initconst =
1358c2ecf20Sopenharmony_ci		KERN_INFO "glob: %u self-tests passed, %u failed\n";
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	/*
1388c2ecf20Sopenharmony_ci	 * Tests are jammed together in a string.  The first byte is '1'
1398c2ecf20Sopenharmony_ci	 * or '0' to indicate the expected outcome, or '\0' to indicate the
1408c2ecf20Sopenharmony_ci	 * end of the tests.  Then come two null-terminated strings: the
1418c2ecf20Sopenharmony_ci	 * pattern and the string to match it against.
1428c2ecf20Sopenharmony_ci	 */
1438c2ecf20Sopenharmony_ci	while (*p) {
1448c2ecf20Sopenharmony_ci		bool expected = *p++ & 1;
1458c2ecf20Sopenharmony_ci		char const *pat = p;
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci		p += strlen(p) + 1;
1488c2ecf20Sopenharmony_ci		successes += test(pat, p, expected);
1498c2ecf20Sopenharmony_ci		p += strlen(p) + 1;
1508c2ecf20Sopenharmony_ci		n++;
1518c2ecf20Sopenharmony_ci	}
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci	n -= successes;
1548c2ecf20Sopenharmony_ci	printk(message, successes, n);
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci	/* What's the errno for "kernel bug detected"?  Guess... */
1578c2ecf20Sopenharmony_ci	return n ? -ECANCELED : 0;
1588c2ecf20Sopenharmony_ci}
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci/* We need a dummy exit function to allow unload */
1618c2ecf20Sopenharmony_cistatic void __exit glob_fini(void) { }
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_cimodule_init(glob_init);
1648c2ecf20Sopenharmony_cimodule_exit(glob_fini);
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("glob(7) matching tests");
1678c2ecf20Sopenharmony_ciMODULE_LICENSE("Dual MIT/GPL");
168