#include #include #include #define APR_FNM_NOMATCH 1 /**< Match failed. */ #define APR_FNM_NOESCAPE 0x01 /**< Disable backslash escaping. */ #define APR_FNM_PATHNAME 0x02 /**< Slash must be matched by slash. */ #define APR_FNM_PERIOD 0x04 /**< Leading period must be matched by period. */ #define APR_FNM_CASE_BLIND 0x08 /**< Compare characters case-insensitively. */ #ifdef __cplusplus extern "C" { #endif typedef int (*apr_fnmatch_t)(const char *pattern, const char *strings, int flags); apr_fnmatch_t apr_fnmatch; #ifdef __cplusplus } #endif static void* get_sym(void *lib_handle, const char *symbol); static void test_fnmatch(); int main(int argc, char **argv) { void *lib_handle; lib_handle = dlopen("/lib64/libapr-1.so.0", RTLD_LAZY); if (!lib_handle) { fprintf(stderr, "%s\n", dlerror()); exit(1); } apr_fnmatch = (apr_fnmatch_t) get_sym(lib_handle, "apr_fnmatch"); test_fnmatch(); dlclose(lib_handle); return 0; } static void* get_sym(void *lib_handle, const char *symbol) { void *result = dlsym(lib_handle, symbol); char *error; if ((error = dlerror()) != NULL) { fprintf(stderr, "%s\n", error); exit(1); } return result; } #define APR_FNM_BITS 15 #define APR_FNM_FAILBIT 256 #define FAILS_IF(X) 0, X #define SUCCEEDS_IF(X) X, 256 #define SUCCEEDS 0, 256 #define FAILS 256, 0 static struct pattern_s { const char *pattern; const char *string; int require_flags; int fail_flags; } patterns[] = { /* Pattern, String to Test, Flags to Match */ {"", "test", FAILS}, {"", "*", FAILS}, {"test", "*", FAILS}, {"test", "test", SUCCEEDS}, /* Remember C '\\' is a single backslash in pattern */ {"te\\st", "test", FAILS_IF(APR_FNM_NOESCAPE)}, {"te\\\\st", "te\\st", FAILS_IF(APR_FNM_NOESCAPE)}, {"te\\*t", "te*t", FAILS_IF(APR_FNM_NOESCAPE)}, {"te\\*t", "test", FAILS}, {"te\\?t", "te?t", FAILS_IF(APR_FNM_NOESCAPE)}, {"te\\?t", "test", FAILS}, {"tesT", "test", SUCCEEDS_IF(APR_FNM_CASE_BLIND)}, {"test", "Test", SUCCEEDS_IF(APR_FNM_CASE_BLIND)}, {"tEst", "teSt", SUCCEEDS_IF(APR_FNM_CASE_BLIND)}, {"?est", "test", SUCCEEDS}, {"te?t", "test", SUCCEEDS}, {"tes?", "test", SUCCEEDS}, {"test?", "test", FAILS}, {"*", "", SUCCEEDS}, {"*", "test", SUCCEEDS}, {"*test", "test", SUCCEEDS}, {"*est", "test", SUCCEEDS}, {"*st", "test", SUCCEEDS}, {"t*t", "test", SUCCEEDS}, {"te*t", "test", SUCCEEDS}, {"te*st", "test", SUCCEEDS}, {"te*", "test", SUCCEEDS}, {"tes*", "test", SUCCEEDS}, {"test*", "test", SUCCEEDS}, {".[\\-\\t]", ".t", SUCCEEDS}, {"test*?*[a-z]*", "testgoop", SUCCEEDS}, {"te[^x]t", "test", SUCCEEDS}, {"te[^abc]t", "test", SUCCEEDS}, {"te[^x]t", "test", SUCCEEDS}, {"te[!x]t", "test", SUCCEEDS}, {"te[^x]t", "text", FAILS}, {"te[^\\x]t", "text", FAILS}, {"te[^x\\", "text", FAILS}, {"te[/]t", "text", FAILS}, {"te[S]t", "test", SUCCEEDS_IF(APR_FNM_CASE_BLIND)}, {"te[r-t]t", "test", SUCCEEDS}, {"te[r-t]t", "teSt", SUCCEEDS_IF(APR_FNM_CASE_BLIND)}, {"te[r-T]t", "test", SUCCEEDS_IF(APR_FNM_CASE_BLIND)}, {"te[R-T]t", "test", SUCCEEDS_IF(APR_FNM_CASE_BLIND)}, {"te[r-Tz]t", "tezt", SUCCEEDS}, {"te[R-T]t", "tent", FAILS}, {"tes[]t]", "test", SUCCEEDS}, {"tes[t-]", "test", SUCCEEDS}, {"tes[t-]]", "test]", SUCCEEDS}, {"tes[t-]]", "test", FAILS}, {"tes[u-]", "test", FAILS}, {"tes[t-]", "tes[t-]", FAILS}, {"test[/-/]", "test[/-/]", SUCCEEDS_IF(APR_FNM_PATHNAME)}, {"test[\\/-/]", "test[/-/]", APR_FNM_PATHNAME, APR_FNM_NOESCAPE}, {"test[/-\\/]", "test[/-/]", APR_FNM_PATHNAME, APR_FNM_NOESCAPE}, {"test[/-/]", "test/", FAILS_IF(APR_FNM_PATHNAME)}, {"test[\\/-/]", "test/", FAILS_IF(APR_FNM_PATHNAME)}, {"test[/-\\/]", "test/", FAILS_IF(APR_FNM_PATHNAME)}, {"/", "", FAILS}, {"", "/", FAILS}, {"/test", "test", FAILS}, {"test", "/test", FAILS}, {"test/", "test", FAILS}, {"test", "test/", FAILS}, {"\\/test", "/test", FAILS_IF(APR_FNM_NOESCAPE)}, {"*test", "/test", FAILS_IF(APR_FNM_PATHNAME)}, {"/*/test/", "/test", FAILS}, {"/*/test/", "/test/test/", SUCCEEDS}, {"test/this", "test/", FAILS}, {"test/", "test/this", FAILS}, {"test*/this", "test/this", SUCCEEDS}, {"test*/this", "test/that", FAILS}, {"test/*this", "test/this", SUCCEEDS}, {".*", ".this", SUCCEEDS}, {"*", ".this", FAILS_IF(APR_FNM_PERIOD)}, {"?this", ".this", FAILS_IF(APR_FNM_PERIOD)}, {"[.]this", ".this", FAILS_IF(APR_FNM_PERIOD)}, {"test/this", "test/this", SUCCEEDS}, {"test?this", "test/this", FAILS_IF(APR_FNM_PATHNAME)}, {"test*this", "test/this", FAILS_IF(APR_FNM_PATHNAME)}, {"test[/]this", "test/this", FAILS_IF(APR_FNM_PATHNAME)}, {"test/.*", "test/.this", SUCCEEDS}, {"test/*", "test/.this", FAILS_IF(APR_FNM_PERIOD | APR_FNM_PATHNAME)}, {"test/?this", "test/.this", FAILS_IF(APR_FNM_PERIOD | APR_FNM_PATHNAME)}, {"test/[.]this", "test/.this", FAILS_IF(APR_FNM_PERIOD | APR_FNM_PATHNAME)}, // My tests. {"foo[[]bar", "foo[bar", SUCCEEDS}, {"foo]bar", "foo]bar", SUCCEEDS}, {"foo[[]]bar", "foo[]bar", SUCCEEDS}, {"foo[]bar", "foobar", FAILS}, {"foo[]]bar", "foo]bar", FAILS}, {"foo[!]bar", "foobar", SUCCEEDS}, {"foo[^]bar", "foobar", SUCCEEDS}, {"foo[!]]bar", "foo]bar", SUCCEEDS}, {"foo[^]]bar", "foo]bar", SUCCEEDS}, {"foo[!]]bar", "fooXbar", FAILS}, {"foo[^]]bar", "fooXbar", FAILS}, {NULL, NULL, 0} }; static void test_fnmatch() { struct pattern_s *test = patterns; int i = APR_FNM_BITS + 1; int res; for (test = patterns; test->pattern; ++test) { for (i = 0; i <= APR_FNM_BITS; ++i) { res = apr_fnmatch(test->pattern, test->string, i); if (((i & test->require_flags) != test->require_flags) || ((i & test->fail_flags) == test->fail_flags)) { if (res != APR_FNM_NOMATCH) break; } else { if (res != 0) break; } } if (i <= APR_FNM_BITS) { printf("apr_fnmatch(\"%s\", \"%s\", %d) returns %d\n", test->pattern, test->string, i, res); } } printf("done test_fnmatch\n"); }