1*57718be8SEnji Cooper /* $NetBSD: t_glob.c,v 1.3 2013/01/02 11:28:48 martin Exp $ */ 2*57718be8SEnji Cooper /*- 3*57718be8SEnji Cooper * Copyright (c) 2010 The NetBSD Foundation, Inc. 4*57718be8SEnji Cooper * All rights reserved. 5*57718be8SEnji Cooper * 6*57718be8SEnji Cooper * This code is derived from software contributed to The NetBSD Foundation 7*57718be8SEnji Cooper * by Christos Zoulas 8*57718be8SEnji Cooper * 9*57718be8SEnji Cooper * Redistribution and use in source and binary forms, with or without 10*57718be8SEnji Cooper * modification, are permitted provided that the following conditions 11*57718be8SEnji Cooper * are met: 12*57718be8SEnji Cooper * 13*57718be8SEnji Cooper * 1. Redistributions of source code must retain the above copyright 14*57718be8SEnji Cooper * notice, this list of conditions and the following disclaimer. 15*57718be8SEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright 16*57718be8SEnji Cooper * notice, this list of conditions and the following disclaimer in 17*57718be8SEnji Cooper * the documentation and/or other materials provided with the 18*57718be8SEnji Cooper * distribution. 19*57718be8SEnji Cooper * 20*57718be8SEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21*57718be8SEnji Cooper * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22*57718be8SEnji Cooper * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23*57718be8SEnji Cooper * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24*57718be8SEnji Cooper * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25*57718be8SEnji Cooper * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 26*57718be8SEnji Cooper * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27*57718be8SEnji Cooper * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28*57718be8SEnji Cooper * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29*57718be8SEnji Cooper * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 30*57718be8SEnji Cooper * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31*57718be8SEnji Cooper * SUCH DAMAGE. 32*57718be8SEnji Cooper */ 33*57718be8SEnji Cooper 34*57718be8SEnji Cooper #include <sys/cdefs.h> 35*57718be8SEnji Cooper __RCSID("$NetBSD: t_glob.c,v 1.3 2013/01/02 11:28:48 martin Exp $"); 36*57718be8SEnji Cooper 37*57718be8SEnji Cooper #include <atf-c.h> 38*57718be8SEnji Cooper 39*57718be8SEnji Cooper #include <sys/param.h> 40*57718be8SEnji Cooper #include <sys/stat.h> 41*57718be8SEnji Cooper 42*57718be8SEnji Cooper #include <dirent.h> 43*57718be8SEnji Cooper #include <glob.h> 44*57718be8SEnji Cooper #include <stdio.h> 45*57718be8SEnji Cooper #include <stdlib.h> 46*57718be8SEnji Cooper #include <string.h> 47*57718be8SEnji Cooper #include <errno.h> 48*57718be8SEnji Cooper 49*57718be8SEnji Cooper #include "../../../h_macros.h" 50*57718be8SEnji Cooper 51*57718be8SEnji Cooper 52*57718be8SEnji Cooper #ifdef DEBUG 53*57718be8SEnji Cooper #define DPRINTF(a) printf a 54*57718be8SEnji Cooper #else 55*57718be8SEnji Cooper #define DPRINTF(a) 56*57718be8SEnji Cooper #endif 57*57718be8SEnji Cooper 58*57718be8SEnji Cooper struct gl_file { 59*57718be8SEnji Cooper const char *name; 60*57718be8SEnji Cooper int dir; 61*57718be8SEnji Cooper }; 62*57718be8SEnji Cooper 63*57718be8SEnji Cooper static struct gl_file a[] = { 64*57718be8SEnji Cooper { "1", 0 }, 65*57718be8SEnji Cooper { "b", 1 }, 66*57718be8SEnji Cooper { "3", 0 }, 67*57718be8SEnji Cooper { "4", 0 }, 68*57718be8SEnji Cooper }; 69*57718be8SEnji Cooper 70*57718be8SEnji Cooper static struct gl_file b[] = { 71*57718be8SEnji Cooper { "x", 0 }, 72*57718be8SEnji Cooper { "y", 0 }, 73*57718be8SEnji Cooper { "z", 0 }, 74*57718be8SEnji Cooper { "w", 0 }, 75*57718be8SEnji Cooper }; 76*57718be8SEnji Cooper 77*57718be8SEnji Cooper struct gl_dir { 78*57718be8SEnji Cooper const char *name; /* directory name */ 79*57718be8SEnji Cooper const struct gl_file *dir; 80*57718be8SEnji Cooper size_t len, pos; 81*57718be8SEnji Cooper }; 82*57718be8SEnji Cooper 83*57718be8SEnji Cooper static struct gl_dir d[] = { 84*57718be8SEnji Cooper { "a", a, __arraycount(a), 0 }, 85*57718be8SEnji Cooper { "a/b", b, __arraycount(b), 0 }, 86*57718be8SEnji Cooper }; 87*57718be8SEnji Cooper 88*57718be8SEnji Cooper static const char *glob_star[] = { 89*57718be8SEnji Cooper "a/1", "a/3", "a/4", "a/b", "a/b/w", "a/b/x", "a/b/y", "a/b/z", 90*57718be8SEnji Cooper }; 91*57718be8SEnji Cooper 92*57718be8SEnji Cooper static const char *glob_star_not[] = { 93*57718be8SEnji Cooper "a/1", "a/3", "a/4", "a/b", 94*57718be8SEnji Cooper }; 95*57718be8SEnji Cooper 96*57718be8SEnji Cooper static void 97*57718be8SEnji Cooper trim(char *buf, size_t len, const char *name) 98*57718be8SEnji Cooper { 99*57718be8SEnji Cooper char *path = buf, *epath = buf + len; 100*57718be8SEnji Cooper while (path < epath && (*path++ = *name++) != '\0') 101*57718be8SEnji Cooper continue; 102*57718be8SEnji Cooper path--; 103*57718be8SEnji Cooper while (path > buf && *--path == '/') 104*57718be8SEnji Cooper *path = '\0'; 105*57718be8SEnji Cooper } 106*57718be8SEnji Cooper 107*57718be8SEnji Cooper static void * 108*57718be8SEnji Cooper gl_opendir(const char *dir) 109*57718be8SEnji Cooper { 110*57718be8SEnji Cooper size_t i; 111*57718be8SEnji Cooper char buf[MAXPATHLEN]; 112*57718be8SEnji Cooper trim(buf, sizeof(buf), dir); 113*57718be8SEnji Cooper 114*57718be8SEnji Cooper for (i = 0; i < __arraycount(d); i++) 115*57718be8SEnji Cooper if (strcmp(buf, d[i].name) == 0) { 116*57718be8SEnji Cooper DPRINTF(("opendir %s %zu\n", buf, i)); 117*57718be8SEnji Cooper return &d[i]; 118*57718be8SEnji Cooper } 119*57718be8SEnji Cooper errno = ENOENT; 120*57718be8SEnji Cooper return NULL; 121*57718be8SEnji Cooper } 122*57718be8SEnji Cooper 123*57718be8SEnji Cooper static struct dirent * 124*57718be8SEnji Cooper gl_readdir(void *v) 125*57718be8SEnji Cooper { 126*57718be8SEnji Cooper static struct dirent dir; 127*57718be8SEnji Cooper struct gl_dir *dd = v; 128*57718be8SEnji Cooper if (dd->pos < dd->len) { 129*57718be8SEnji Cooper const struct gl_file *f = &dd->dir[dd->pos++]; 130*57718be8SEnji Cooper strcpy(dir.d_name, f->name); 131*57718be8SEnji Cooper dir.d_namlen = strlen(f->name); 132*57718be8SEnji Cooper dir.d_ino = dd->pos; 133*57718be8SEnji Cooper dir.d_type = f->dir ? DT_DIR : DT_REG; 134*57718be8SEnji Cooper DPRINTF(("readdir %s %d\n", dir.d_name, dir.d_type)); 135*57718be8SEnji Cooper dir.d_reclen = _DIRENT_RECLEN(&dir, dir.d_namlen); 136*57718be8SEnji Cooper return &dir; 137*57718be8SEnji Cooper } 138*57718be8SEnji Cooper return NULL; 139*57718be8SEnji Cooper } 140*57718be8SEnji Cooper 141*57718be8SEnji Cooper static int 142*57718be8SEnji Cooper gl_stat(const char *name , __gl_stat_t *st) 143*57718be8SEnji Cooper { 144*57718be8SEnji Cooper char buf[MAXPATHLEN]; 145*57718be8SEnji Cooper trim(buf, sizeof(buf), name); 146*57718be8SEnji Cooper memset(st, 0, sizeof(*st)); 147*57718be8SEnji Cooper 148*57718be8SEnji Cooper if (strcmp(buf, "a") == 0 || strcmp(buf, "a/b") == 0) { 149*57718be8SEnji Cooper st->st_mode |= _S_IFDIR; 150*57718be8SEnji Cooper return 0; 151*57718be8SEnji Cooper } 152*57718be8SEnji Cooper 153*57718be8SEnji Cooper if (buf[0] == 'a' && buf[1] == '/') { 154*57718be8SEnji Cooper struct gl_file *f; 155*57718be8SEnji Cooper size_t offs, count; 156*57718be8SEnji Cooper 157*57718be8SEnji Cooper if (buf[2] == 'b' && buf[3] == '/') { 158*57718be8SEnji Cooper offs = 4; 159*57718be8SEnji Cooper count = __arraycount(b); 160*57718be8SEnji Cooper f = b; 161*57718be8SEnji Cooper } else { 162*57718be8SEnji Cooper offs = 2; 163*57718be8SEnji Cooper count = __arraycount(a); 164*57718be8SEnji Cooper f = a; 165*57718be8SEnji Cooper } 166*57718be8SEnji Cooper 167*57718be8SEnji Cooper for (size_t i = 0; i < count; i++) 168*57718be8SEnji Cooper if (strcmp(f[i].name, buf + offs) == 0) 169*57718be8SEnji Cooper return 0; 170*57718be8SEnji Cooper } 171*57718be8SEnji Cooper DPRINTF(("stat %s %d\n", buf, st->st_mode)); 172*57718be8SEnji Cooper errno = ENOENT; 173*57718be8SEnji Cooper return -1; 174*57718be8SEnji Cooper } 175*57718be8SEnji Cooper 176*57718be8SEnji Cooper static int 177*57718be8SEnji Cooper gl_lstat(const char *name , __gl_stat_t *st) 178*57718be8SEnji Cooper { 179*57718be8SEnji Cooper return gl_stat(name, st); 180*57718be8SEnji Cooper } 181*57718be8SEnji Cooper 182*57718be8SEnji Cooper static void 183*57718be8SEnji Cooper gl_closedir(void *v) 184*57718be8SEnji Cooper { 185*57718be8SEnji Cooper struct gl_dir *dd = v; 186*57718be8SEnji Cooper dd->pos = 0; 187*57718be8SEnji Cooper DPRINTF(("closedir %p\n", dd)); 188*57718be8SEnji Cooper } 189*57718be8SEnji Cooper 190*57718be8SEnji Cooper static void 191*57718be8SEnji Cooper run(const char *p, int flags, const char **res, size_t len) 192*57718be8SEnji Cooper { 193*57718be8SEnji Cooper glob_t gl; 194*57718be8SEnji Cooper size_t i; 195*57718be8SEnji Cooper 196*57718be8SEnji Cooper memset(&gl, 0, sizeof(gl)); 197*57718be8SEnji Cooper gl.gl_opendir = gl_opendir; 198*57718be8SEnji Cooper gl.gl_readdir = gl_readdir; 199*57718be8SEnji Cooper gl.gl_closedir = gl_closedir; 200*57718be8SEnji Cooper gl.gl_stat = gl_stat; 201*57718be8SEnji Cooper gl.gl_lstat = gl_lstat; 202*57718be8SEnji Cooper 203*57718be8SEnji Cooper RZ(glob(p, GLOB_ALTDIRFUNC | flags, NULL, &gl)); 204*57718be8SEnji Cooper 205*57718be8SEnji Cooper for (i = 0; i < gl.gl_pathc; i++) 206*57718be8SEnji Cooper DPRINTF(("%s\n", gl.gl_pathv[i])); 207*57718be8SEnji Cooper 208*57718be8SEnji Cooper ATF_CHECK(len == gl.gl_pathc); 209*57718be8SEnji Cooper for (i = 0; i < gl.gl_pathc; i++) 210*57718be8SEnji Cooper ATF_CHECK_STREQ(gl.gl_pathv[i], res[i]); 211*57718be8SEnji Cooper 212*57718be8SEnji Cooper globfree(&gl); 213*57718be8SEnji Cooper } 214*57718be8SEnji Cooper 215*57718be8SEnji Cooper 216*57718be8SEnji Cooper ATF_TC(glob_star); 217*57718be8SEnji Cooper ATF_TC_HEAD(glob_star, tc) 218*57718be8SEnji Cooper { 219*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", 220*57718be8SEnji Cooper "Test glob(3) ** with GLOB_STAR"); 221*57718be8SEnji Cooper } 222*57718be8SEnji Cooper 223*57718be8SEnji Cooper ATF_TC_BODY(glob_star, tc) 224*57718be8SEnji Cooper { 225*57718be8SEnji Cooper run("a/**", GLOB_STAR, glob_star, __arraycount(glob_star)); 226*57718be8SEnji Cooper } 227*57718be8SEnji Cooper 228*57718be8SEnji Cooper ATF_TC(glob_star_not); 229*57718be8SEnji Cooper ATF_TC_HEAD(glob_star_not, tc) 230*57718be8SEnji Cooper { 231*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", 232*57718be8SEnji Cooper "Test glob(3) ** without GLOB_STAR"); 233*57718be8SEnji Cooper } 234*57718be8SEnji Cooper 235*57718be8SEnji Cooper 236*57718be8SEnji Cooper ATF_TC_BODY(glob_star_not, tc) 237*57718be8SEnji Cooper { 238*57718be8SEnji Cooper run("a/**", 0, glob_star_not, __arraycount(glob_star_not)); 239*57718be8SEnji Cooper } 240*57718be8SEnji Cooper 241*57718be8SEnji Cooper #if 0 242*57718be8SEnji Cooper ATF_TC(glob_nocheck); 243*57718be8SEnji Cooper ATF_TC_HEAD(glob_nocheck, tc) 244*57718be8SEnji Cooper { 245*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", 246*57718be8SEnji Cooper "Test glob(3) pattern with backslash and GLOB_NOCHECK"); 247*57718be8SEnji Cooper } 248*57718be8SEnji Cooper 249*57718be8SEnji Cooper 250*57718be8SEnji Cooper ATF_TC_BODY(glob_nocheck, tc) 251*57718be8SEnji Cooper { 252*57718be8SEnji Cooper static const char pattern[] = { 'f', 'o', 'o', '\\', ';', 'b', 'a', 253*57718be8SEnji Cooper 'r', '\0' }; 254*57718be8SEnji Cooper static const char *glob_nocheck[] = { 255*57718be8SEnji Cooper pattern 256*57718be8SEnji Cooper }; 257*57718be8SEnji Cooper run(pattern, GLOB_NOCHECK, glob_nocheck, __arraycount(glob_nocheck)); 258*57718be8SEnji Cooper } 259*57718be8SEnji Cooper #endif 260*57718be8SEnji Cooper 261*57718be8SEnji Cooper ATF_TP_ADD_TCS(tp) 262*57718be8SEnji Cooper { 263*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, glob_star); 264*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, glob_star_not); 265*57718be8SEnji Cooper /* 266*57718be8SEnji Cooper * Remove this test for now - the GLOB_NOCHECK return value has been 267*57718be8SEnji Cooper * re-defined to return a modified pattern in revision 1.33 of glob.c 268*57718be8SEnji Cooper * 269*57718be8SEnji Cooper * ATF_TP_ADD_TC(tp, glob_nocheck); 270*57718be8SEnji Cooper */ 271*57718be8SEnji Cooper 272*57718be8SEnji Cooper return atf_no_error(); 273*57718be8SEnji Cooper } 274