1314817Sngie/* $NetBSD: t_glob.c,v 1.5 2017/01/14 20:47:41 christos Exp $ */ 2272343Sngie/*- 3272343Sngie * Copyright (c) 2010 The NetBSD Foundation, Inc. 4272343Sngie * All rights reserved. 5272343Sngie * 6272343Sngie * This code is derived from software contributed to The NetBSD Foundation 7272343Sngie * by Christos Zoulas 8272343Sngie * 9272343Sngie * Redistribution and use in source and binary forms, with or without 10272343Sngie * modification, are permitted provided that the following conditions 11272343Sngie * are met: 12272343Sngie * 13272343Sngie * 1. Redistributions of source code must retain the above copyright 14272343Sngie * notice, this list of conditions and the following disclaimer. 15272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 16272343Sngie * notice, this list of conditions and the following disclaimer in 17272343Sngie * the documentation and/or other materials provided with the 18272343Sngie * distribution. 19272343Sngie * 20272343Sngie * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21272343Sngie * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22272343Sngie * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23272343Sngie * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24272343Sngie * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25272343Sngie * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 26272343Sngie * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27272343Sngie * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28272343Sngie * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29272343Sngie * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 30272343Sngie * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31272343Sngie * SUCH DAMAGE. 32272343Sngie */ 33272343Sngie 34272343Sngie#include <sys/cdefs.h> 35314817Sngie__RCSID("$NetBSD: t_glob.c,v 1.5 2017/01/14 20:47:41 christos Exp $"); 36272343Sngie 37272343Sngie#include <atf-c.h> 38272343Sngie 39272343Sngie#include <sys/param.h> 40272343Sngie#include <sys/stat.h> 41272343Sngie 42272343Sngie#include <dirent.h> 43272343Sngie#include <glob.h> 44272343Sngie#include <stdio.h> 45272343Sngie#include <stdlib.h> 46272343Sngie#include <string.h> 47272343Sngie#include <errno.h> 48272343Sngie 49276478Sngie#include "h_macros.h" 50272343Sngie 51272343Sngie 52272343Sngie#ifdef DEBUG 53272343Sngie#define DPRINTF(a) printf a 54272343Sngie#else 55272343Sngie#define DPRINTF(a) 56272343Sngie#endif 57272343Sngie 58272343Sngiestruct gl_file { 59272343Sngie const char *name; 60272343Sngie int dir; 61272343Sngie}; 62272343Sngie 63272343Sngiestatic struct gl_file a[] = { 64272343Sngie { "1", 0 }, 65272343Sngie { "b", 1 }, 66272343Sngie { "3", 0 }, 67272343Sngie { "4", 0 }, 68272343Sngie}; 69272343Sngie 70272343Sngiestatic struct gl_file b[] = { 71272343Sngie { "x", 0 }, 72272343Sngie { "y", 0 }, 73272343Sngie { "z", 0 }, 74272343Sngie { "w", 0 }, 75272343Sngie}; 76272343Sngie 77272343Sngiestruct gl_dir { 78272343Sngie const char *name; /* directory name */ 79272343Sngie const struct gl_file *dir; 80272343Sngie size_t len, pos; 81272343Sngie}; 82272343Sngie 83272343Sngiestatic struct gl_dir d[] = { 84272343Sngie { "a", a, __arraycount(a), 0 }, 85272343Sngie { "a/b", b, __arraycount(b), 0 }, 86272343Sngie}; 87272343Sngie 88314817Sngie#ifdef GLOB_STAR 89272343Sngiestatic const char *glob_star[] = { 90272343Sngie "a/1", "a/3", "a/4", "a/b", "a/b/w", "a/b/x", "a/b/y", "a/b/z", 91272343Sngie}; 92291044Sngie#endif 93272343Sngie 94272343Sngiestatic const char *glob_star_not[] = { 95272343Sngie "a/1", "a/3", "a/4", "a/b", 96272343Sngie}; 97272343Sngie 98272343Sngiestatic void 99272343Sngietrim(char *buf, size_t len, const char *name) 100272343Sngie{ 101272343Sngie char *path = buf, *epath = buf + len; 102272343Sngie while (path < epath && (*path++ = *name++) != '\0') 103272343Sngie continue; 104272343Sngie path--; 105272343Sngie while (path > buf && *--path == '/') 106272343Sngie *path = '\0'; 107272343Sngie} 108272343Sngie 109272343Sngiestatic void * 110272343Sngiegl_opendir(const char *dir) 111272343Sngie{ 112272343Sngie size_t i; 113272343Sngie char buf[MAXPATHLEN]; 114272343Sngie trim(buf, sizeof(buf), dir); 115272343Sngie 116272343Sngie for (i = 0; i < __arraycount(d); i++) 117272343Sngie if (strcmp(buf, d[i].name) == 0) { 118272343Sngie DPRINTF(("opendir %s %zu\n", buf, i)); 119272343Sngie return &d[i]; 120272343Sngie } 121272343Sngie errno = ENOENT; 122272343Sngie return NULL; 123272343Sngie} 124272343Sngie 125272343Sngiestatic struct dirent * 126272343Sngiegl_readdir(void *v) 127272343Sngie{ 128272343Sngie static struct dirent dir; 129272343Sngie struct gl_dir *dd = v; 130272343Sngie if (dd->pos < dd->len) { 131272343Sngie const struct gl_file *f = &dd->dir[dd->pos++]; 132272343Sngie strcpy(dir.d_name, f->name); 133272343Sngie dir.d_namlen = strlen(f->name); 134272343Sngie dir.d_ino = dd->pos; 135272343Sngie dir.d_type = f->dir ? DT_DIR : DT_REG; 136272343Sngie DPRINTF(("readdir %s %d\n", dir.d_name, dir.d_type)); 137276478Sngie#ifdef __FreeBSD__ 138276478Sngie dir.d_reclen = -1; /* Does not have _DIRENT_RECLEN */ 139276478Sngie#else 140272343Sngie dir.d_reclen = _DIRENT_RECLEN(&dir, dir.d_namlen); 141276478Sngie#endif 142272343Sngie return &dir; 143272343Sngie } 144272343Sngie return NULL; 145272343Sngie} 146272343Sngie 147272343Sngiestatic int 148272343Sngiegl_stat(const char *name , __gl_stat_t *st) 149272343Sngie{ 150272343Sngie char buf[MAXPATHLEN]; 151272343Sngie trim(buf, sizeof(buf), name); 152272343Sngie memset(st, 0, sizeof(*st)); 153272343Sngie 154272343Sngie if (strcmp(buf, "a") == 0 || strcmp(buf, "a/b") == 0) { 155314817Sngie st->st_mode |= S_IFDIR; 156272343Sngie return 0; 157272343Sngie } 158272343Sngie 159272343Sngie if (buf[0] == 'a' && buf[1] == '/') { 160272343Sngie struct gl_file *f; 161272343Sngie size_t offs, count; 162272343Sngie 163272343Sngie if (buf[2] == 'b' && buf[3] == '/') { 164272343Sngie offs = 4; 165272343Sngie count = __arraycount(b); 166272343Sngie f = b; 167272343Sngie } else { 168272343Sngie offs = 2; 169272343Sngie count = __arraycount(a); 170272343Sngie f = a; 171272343Sngie } 172272343Sngie 173272343Sngie for (size_t i = 0; i < count; i++) 174272343Sngie if (strcmp(f[i].name, buf + offs) == 0) 175272343Sngie return 0; 176272343Sngie } 177272343Sngie DPRINTF(("stat %s %d\n", buf, st->st_mode)); 178272343Sngie errno = ENOENT; 179272343Sngie return -1; 180272343Sngie} 181272343Sngie 182272343Sngiestatic int 183272343Sngiegl_lstat(const char *name , __gl_stat_t *st) 184272343Sngie{ 185272343Sngie return gl_stat(name, st); 186272343Sngie} 187272343Sngie 188272343Sngiestatic void 189272343Sngiegl_closedir(void *v) 190272343Sngie{ 191272343Sngie struct gl_dir *dd = v; 192272343Sngie dd->pos = 0; 193272343Sngie DPRINTF(("closedir %p\n", dd)); 194272343Sngie} 195272343Sngie 196272343Sngiestatic void 197272343Sngierun(const char *p, int flags, const char **res, size_t len) 198272343Sngie{ 199272343Sngie glob_t gl; 200272343Sngie size_t i; 201272343Sngie 202272343Sngie memset(&gl, 0, sizeof(gl)); 203272343Sngie gl.gl_opendir = gl_opendir; 204272343Sngie gl.gl_readdir = gl_readdir; 205272343Sngie gl.gl_closedir = gl_closedir; 206272343Sngie gl.gl_stat = gl_stat; 207272343Sngie gl.gl_lstat = gl_lstat; 208272343Sngie 209272343Sngie RZ(glob(p, GLOB_ALTDIRFUNC | flags, NULL, &gl)); 210272343Sngie 211272343Sngie for (i = 0; i < gl.gl_pathc; i++) 212272343Sngie DPRINTF(("%s\n", gl.gl_pathv[i])); 213272343Sngie 214272343Sngie ATF_CHECK(len == gl.gl_pathc); 215272343Sngie for (i = 0; i < gl.gl_pathc; i++) 216272343Sngie ATF_CHECK_STREQ(gl.gl_pathv[i], res[i]); 217272343Sngie 218272343Sngie globfree(&gl); 219272343Sngie} 220272343Sngie 221272343Sngie 222314817Sngie#ifdef GLOB_STAR 223272343SngieATF_TC(glob_star); 224272343SngieATF_TC_HEAD(glob_star, tc) 225272343Sngie{ 226272343Sngie atf_tc_set_md_var(tc, "descr", 227272343Sngie "Test glob(3) ** with GLOB_STAR"); 228272343Sngie} 229272343Sngie 230272343SngieATF_TC_BODY(glob_star, tc) 231272343Sngie{ 232272343Sngie run("a/**", GLOB_STAR, glob_star, __arraycount(glob_star)); 233272343Sngie} 234276478Sngie#endif 235272343Sngie 236272343SngieATF_TC(glob_star_not); 237272343SngieATF_TC_HEAD(glob_star_not, tc) 238272343Sngie{ 239272343Sngie atf_tc_set_md_var(tc, "descr", 240272343Sngie "Test glob(3) ** without GLOB_STAR"); 241272343Sngie} 242272343Sngie 243272343Sngie 244272343SngieATF_TC_BODY(glob_star_not, tc) 245272343Sngie{ 246272343Sngie run("a/**", 0, glob_star_not, __arraycount(glob_star_not)); 247272343Sngie} 248272343Sngie 249272343Sngie#if 0 250272343SngieATF_TC(glob_nocheck); 251272343SngieATF_TC_HEAD(glob_nocheck, tc) 252272343Sngie{ 253272343Sngie atf_tc_set_md_var(tc, "descr", 254272343Sngie "Test glob(3) pattern with backslash and GLOB_NOCHECK"); 255272343Sngie} 256272343Sngie 257272343Sngie 258272343SngieATF_TC_BODY(glob_nocheck, tc) 259272343Sngie{ 260272343Sngie static const char pattern[] = { 'f', 'o', 'o', '\\', ';', 'b', 'a', 261272343Sngie 'r', '\0' }; 262272343Sngie static const char *glob_nocheck[] = { 263272343Sngie pattern 264272343Sngie }; 265272343Sngie run(pattern, GLOB_NOCHECK, glob_nocheck, __arraycount(glob_nocheck)); 266272343Sngie} 267272343Sngie#endif 268272343Sngie 269272343SngieATF_TP_ADD_TCS(tp) 270272343Sngie{ 271314817Sngie#ifdef GLOB_STAR 272272343Sngie ATF_TP_ADD_TC(tp, glob_star); 273276478Sngie#endif 274272343Sngie ATF_TP_ADD_TC(tp, glob_star_not); 275272343Sngie/* 276272343Sngie * Remove this test for now - the GLOB_NOCHECK return value has been 277272343Sngie * re-defined to return a modified pattern in revision 1.33 of glob.c 278272343Sngie * 279272343Sngie * ATF_TP_ADD_TC(tp, glob_nocheck); 280272343Sngie */ 281272343Sngie 282272343Sngie return atf_no_error(); 283272343Sngie} 284