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/param.h> 28 #include <errno.h> 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <unistd.h> 33 34 #include <atf-c.h> 35 36 #include "fnmatch_testcases.h" 37 38 static const char * 39 flags_to_string(int flags) 40 { 41 static const int flagvalues[] = { FNM_NOESCAPE, FNM_PATHNAME, 42 FNM_PERIOD, FNM_LEADING_DIR, FNM_CASEFOLD, 0 }; 43 static const char flagnames[] = "FNM_NOESCAPE\0FNM_PATHNAME\0FNM_PERIOD\0FNM_LEADING_DIR\0FNM_CASEFOLD\0"; 44 static char result[sizeof(flagnames) + 3 * sizeof(int) + 2]; 45 char *p; 46 size_t i, len; 47 const char *fp; 48 49 p = result; 50 fp = flagnames; 51 for (i = 0; flagvalues[i] != 0; i++) { 52 len = strlen(fp); 53 if (flags & flagvalues[i]) { 54 if (p != result) 55 *p++ = '|'; 56 memcpy(p, fp, len); 57 p += len; 58 flags &= ~flagvalues[i]; 59 } 60 fp += len + 1; 61 } 62 if (p == result) 63 memcpy(p, "0", 2); 64 else if (flags != 0) 65 sprintf(p, "%d", flags); 66 else 67 *p = '\0'; 68 return result; 69 } 70 71 ATF_TC_WITHOUT_HEAD(fnmatch_test); 72 ATF_TC_BODY(fnmatch_test, tc) 73 { 74 size_t i; 75 int flags, result; 76 struct testcase *t; 77 78 for (i = 0; i < nitems(testcases); i++) { 79 t = &testcases[i]; 80 flags = t->flags; 81 do { 82 result = fnmatch(t->pattern, t->string, flags); 83 if (result != t->result) 84 break; 85 if (strchr(t->pattern, '\\') == NULL && 86 !(flags & FNM_NOESCAPE)) { 87 flags |= FNM_NOESCAPE; 88 result = fnmatch(t->pattern, t->string, flags); 89 if (result != t->result) 90 break; 91 flags = t->flags; 92 } 93 if (strchr(t->pattern, '\\') != NULL && 94 strchr(t->string, '\\') == NULL && 95 t->result == FNM_NOMATCH && 96 !(flags & (FNM_NOESCAPE | FNM_LEADING_DIR))) { 97 flags |= FNM_NOESCAPE; 98 result = fnmatch(t->pattern, t->string, flags); 99 if (result != t->result) 100 break; 101 flags = t->flags; 102 } 103 if ((t->string[0] != '.' || t->pattern[0] == '.' || 104 t->result == FNM_NOMATCH) && 105 !(flags & (FNM_PATHNAME | FNM_PERIOD))) { 106 flags |= FNM_PERIOD; 107 result = fnmatch(t->pattern, t->string, flags); 108 if (result != t->result) 109 break; 110 flags = t->flags; 111 } 112 if ((strchr(t->string, '/') == NULL || 113 t->result == FNM_NOMATCH) && 114 !(flags & FNM_PATHNAME)) { 115 flags |= FNM_PATHNAME; 116 result = fnmatch(t->pattern, t->string, flags); 117 if (result != t->result) 118 break; 119 flags = t->flags; 120 } 121 if ((((t->string[0] != '.' || t->pattern[0] == '.') && 122 strstr(t->string, "/.") == NULL) || 123 t->result == FNM_NOMATCH) && 124 flags & FNM_PATHNAME && !(flags & FNM_PERIOD)) { 125 flags |= FNM_PERIOD; 126 result = fnmatch(t->pattern, t->string, flags); 127 if (result != t->result) 128 break; 129 flags = t->flags; 130 } 131 if ((((t->string[0] != '.' || t->pattern[0] == '.') && 132 strchr(t->string, '/') == NULL) || 133 t->result == FNM_NOMATCH) && 134 !(flags & (FNM_PATHNAME | FNM_PERIOD))) { 135 flags |= FNM_PATHNAME | FNM_PERIOD; 136 result = fnmatch(t->pattern, t->string, flags); 137 if (result != t->result) 138 break; 139 flags = t->flags; 140 } 141 if ((strchr(t->string, '/') == NULL || t->result == 0) 142 && !(flags & FNM_LEADING_DIR)) { 143 flags |= FNM_LEADING_DIR; 144 result = fnmatch(t->pattern, t->string, flags); 145 if (result != t->result) 146 break; 147 flags = t->flags; 148 } 149 if (t->result == 0 && !(flags & FNM_CASEFOLD)) { 150 flags |= FNM_CASEFOLD; 151 result = fnmatch(t->pattern, t->string, flags); 152 if (result != t->result) 153 break; 154 flags = t->flags; 155 } 156 if (strchr(t->pattern, '\\') == NULL && 157 t->result == 0 && 158 !(flags & (FNM_NOESCAPE | FNM_CASEFOLD))) { 159 flags |= FNM_NOESCAPE | FNM_CASEFOLD; 160 result = fnmatch(t->pattern, t->string, flags); 161 if (result != t->result) 162 break; 163 flags = t->flags; 164 } 165 } while (0); 166 167 ATF_CHECK(result == t->result); 168 if (result == t->result) 169 printf("fnmatch(\"%s\", \"%s\", %s) == %d\n", 170 t->pattern, t->string, flags_to_string(flags), result); 171 else 172 printf("fnmatch(\"%s\", \"%s\", %s) != %d (was %d)\n", 173 t->pattern, t->string, flags_to_string(flags), 174 t->result, result); 175 } 176 177 } 178 179 ATF_TP_ADD_TCS(tp) 180 { 181 182 ATF_TP_ADD_TC(tp, fnmatch_test); 183 184 return (atf_no_error()); 185 } 186