1 /*- 2 * Copyright (c) 2010 Jilles Tjoelker 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 #include <sys/param.h> 29 #include <errno.h> 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <string.h> 33 #include <unistd.h> 34 35 #include <atf-c.h> 36 37 #include "fnmatch_testcases.h" 38 39 static const char * 40 flags_to_string(int flags) 41 { 42 static const int flagvalues[] = { FNM_NOESCAPE, FNM_PATHNAME, 43 FNM_PERIOD, FNM_LEADING_DIR, FNM_CASEFOLD, 0 }; 44 static const char flagnames[] = "FNM_NOESCAPE\0FNM_PATHNAME\0FNM_PERIOD\0FNM_LEADING_DIR\0FNM_CASEFOLD\0"; 45 static char result[sizeof(flagnames) + 3 * sizeof(int) + 2]; 46 char *p; 47 size_t i, len; 48 const char *fp; 49 50 p = result; 51 fp = flagnames; 52 for (i = 0; flagvalues[i] != 0; i++) { 53 len = strlen(fp); 54 if (flags & flagvalues[i]) { 55 if (p != result) 56 *p++ = '|'; 57 memcpy(p, fp, len); 58 p += len; 59 flags &= ~flagvalues[i]; 60 } 61 fp += len + 1; 62 } 63 if (p == result) 64 memcpy(p, "0", 2); 65 else if (flags != 0) 66 sprintf(p, "%d", flags); 67 else 68 *p = '\0'; 69 return result; 70 } 71 72 ATF_TC_WITHOUT_HEAD(fnmatch_test); 73 ATF_TC_BODY(fnmatch_test, tc) 74 { 75 size_t i; 76 int flags, result; 77 struct testcase *t; 78 79 for (i = 0; i < nitems(testcases); i++) { 80 t = &testcases[i]; 81 flags = t->flags; 82 do { 83 result = fnmatch(t->pattern, t->string, flags); 84 if (result != t->result) 85 break; 86 if (strchr(t->pattern, '\\') == NULL && 87 !(flags & FNM_NOESCAPE)) { 88 flags |= FNM_NOESCAPE; 89 result = fnmatch(t->pattern, t->string, flags); 90 if (result != t->result) 91 break; 92 flags = t->flags; 93 } 94 if (strchr(t->pattern, '\\') != NULL && 95 strchr(t->string, '\\') == NULL && 96 t->result == FNM_NOMATCH && 97 !(flags & (FNM_NOESCAPE | FNM_LEADING_DIR))) { 98 flags |= FNM_NOESCAPE; 99 result = fnmatch(t->pattern, t->string, flags); 100 if (result != t->result) 101 break; 102 flags = t->flags; 103 } 104 if ((t->string[0] != '.' || t->pattern[0] == '.' || 105 t->result == FNM_NOMATCH) && 106 !(flags & (FNM_PATHNAME | FNM_PERIOD))) { 107 flags |= FNM_PERIOD; 108 result = fnmatch(t->pattern, t->string, flags); 109 if (result != t->result) 110 break; 111 flags = t->flags; 112 } 113 if ((strchr(t->string, '/') == NULL || 114 t->result == FNM_NOMATCH) && 115 !(flags & FNM_PATHNAME)) { 116 flags |= FNM_PATHNAME; 117 result = fnmatch(t->pattern, t->string, flags); 118 if (result != t->result) 119 break; 120 flags = t->flags; 121 } 122 if ((((t->string[0] != '.' || t->pattern[0] == '.') && 123 strstr(t->string, "/.") == NULL) || 124 t->result == FNM_NOMATCH) && 125 flags & FNM_PATHNAME && !(flags & FNM_PERIOD)) { 126 flags |= FNM_PERIOD; 127 result = fnmatch(t->pattern, t->string, flags); 128 if (result != t->result) 129 break; 130 flags = t->flags; 131 } 132 if ((((t->string[0] != '.' || t->pattern[0] == '.') && 133 strchr(t->string, '/') == NULL) || 134 t->result == FNM_NOMATCH) && 135 !(flags & (FNM_PATHNAME | FNM_PERIOD))) { 136 flags |= FNM_PATHNAME | FNM_PERIOD; 137 result = fnmatch(t->pattern, t->string, flags); 138 if (result != t->result) 139 break; 140 flags = t->flags; 141 } 142 if ((strchr(t->string, '/') == NULL || t->result == 0) 143 && !(flags & FNM_LEADING_DIR)) { 144 flags |= FNM_LEADING_DIR; 145 result = fnmatch(t->pattern, t->string, flags); 146 if (result != t->result) 147 break; 148 flags = t->flags; 149 } 150 if (t->result == 0 && !(flags & FNM_CASEFOLD)) { 151 flags |= FNM_CASEFOLD; 152 result = fnmatch(t->pattern, t->string, flags); 153 if (result != t->result) 154 break; 155 flags = t->flags; 156 } 157 if (strchr(t->pattern, '\\') == NULL && 158 t->result == 0 && 159 !(flags & (FNM_NOESCAPE | FNM_CASEFOLD))) { 160 flags |= FNM_NOESCAPE | FNM_CASEFOLD; 161 result = fnmatch(t->pattern, t->string, flags); 162 if (result != t->result) 163 break; 164 flags = t->flags; 165 } 166 } while (0); 167 168 ATF_CHECK(result == t->result); 169 if (result == t->result) 170 printf("fnmatch(\"%s\", \"%s\", %s) == %d\n", 171 t->pattern, t->string, flags_to_string(flags), result); 172 else 173 printf("fnmatch(\"%s\", \"%s\", %s) != %d (was %d)\n", 174 t->pattern, t->string, flags_to_string(flags), 175 t->result, result); 176 } 177 178 } 179 180 ATF_TP_ADD_TCS(tp) 181 { 182 183 ATF_TP_ADD_TC(tp, fnmatch_test); 184 185 return (atf_no_error()); 186 } 187