157718be8SEnji Cooper /* $NetBSD: t_glob.c,v 1.3 2013/01/02 11:28:48 martin Exp $ */ 257718be8SEnji Cooper /*- 357718be8SEnji Cooper * Copyright (c) 2010 The NetBSD Foundation, Inc. 457718be8SEnji Cooper * All rights reserved. 557718be8SEnji Cooper * 657718be8SEnji Cooper * This code is derived from software contributed to The NetBSD Foundation 757718be8SEnji Cooper * by Christos Zoulas 857718be8SEnji Cooper * 957718be8SEnji Cooper * Redistribution and use in source and binary forms, with or without 1057718be8SEnji Cooper * modification, are permitted provided that the following conditions 1157718be8SEnji Cooper * are met: 1257718be8SEnji Cooper * 1357718be8SEnji Cooper * 1. Redistributions of source code must retain the above copyright 1457718be8SEnji Cooper * notice, this list of conditions and the following disclaimer. 1557718be8SEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright 1657718be8SEnji Cooper * notice, this list of conditions and the following disclaimer in 1757718be8SEnji Cooper * the documentation and/or other materials provided with the 1857718be8SEnji Cooper * distribution. 1957718be8SEnji Cooper * 2057718be8SEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2157718be8SEnji Cooper * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2257718be8SEnji Cooper * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 2357718be8SEnji Cooper * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 2457718be8SEnji Cooper * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 2557718be8SEnji Cooper * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 2657718be8SEnji Cooper * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 2757718be8SEnji Cooper * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 2857718be8SEnji Cooper * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 2957718be8SEnji Cooper * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 3057718be8SEnji Cooper * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3157718be8SEnji Cooper * SUCH DAMAGE. 3257718be8SEnji Cooper */ 3357718be8SEnji Cooper 3457718be8SEnji Cooper #include <sys/cdefs.h> 3557718be8SEnji Cooper __RCSID("$NetBSD: t_glob.c,v 1.3 2013/01/02 11:28:48 martin Exp $"); 3657718be8SEnji Cooper 3757718be8SEnji Cooper #include <atf-c.h> 3857718be8SEnji Cooper 3957718be8SEnji Cooper #include <sys/param.h> 4057718be8SEnji Cooper #include <sys/stat.h> 4157718be8SEnji Cooper 4257718be8SEnji Cooper #include <dirent.h> 4357718be8SEnji Cooper #include <glob.h> 4457718be8SEnji Cooper #include <stdio.h> 4557718be8SEnji Cooper #include <stdlib.h> 4657718be8SEnji Cooper #include <string.h> 4757718be8SEnji Cooper #include <errno.h> 4857718be8SEnji Cooper 49*8b8647bfSEnji Cooper #if defined(__FreeBSD__) 50*8b8647bfSEnji Cooper #include "h_macros.h" 51*8b8647bfSEnji Cooper #define __gl_stat_t struct stat 52*8b8647bfSEnji Cooper #define _S_IFDIR S_IFDIR 53*8b8647bfSEnji Cooper #else 5457718be8SEnji Cooper #include "../../../h_macros.h" 55*8b8647bfSEnji Cooper #endif 5657718be8SEnji Cooper 5757718be8SEnji Cooper 5857718be8SEnji Cooper #ifdef DEBUG 5957718be8SEnji Cooper #define DPRINTF(a) printf a 6057718be8SEnji Cooper #else 6157718be8SEnji Cooper #define DPRINTF(a) 6257718be8SEnji Cooper #endif 6357718be8SEnji Cooper 6457718be8SEnji Cooper struct gl_file { 6557718be8SEnji Cooper const char *name; 6657718be8SEnji Cooper int dir; 6757718be8SEnji Cooper }; 6857718be8SEnji Cooper 6957718be8SEnji Cooper static struct gl_file a[] = { 7057718be8SEnji Cooper { "1", 0 }, 7157718be8SEnji Cooper { "b", 1 }, 7257718be8SEnji Cooper { "3", 0 }, 7357718be8SEnji Cooper { "4", 0 }, 7457718be8SEnji Cooper }; 7557718be8SEnji Cooper 7657718be8SEnji Cooper static struct gl_file b[] = { 7757718be8SEnji Cooper { "x", 0 }, 7857718be8SEnji Cooper { "y", 0 }, 7957718be8SEnji Cooper { "z", 0 }, 8057718be8SEnji Cooper { "w", 0 }, 8157718be8SEnji Cooper }; 8257718be8SEnji Cooper 8357718be8SEnji Cooper struct gl_dir { 8457718be8SEnji Cooper const char *name; /* directory name */ 8557718be8SEnji Cooper const struct gl_file *dir; 8657718be8SEnji Cooper size_t len, pos; 8757718be8SEnji Cooper }; 8857718be8SEnji Cooper 8957718be8SEnji Cooper static struct gl_dir d[] = { 9057718be8SEnji Cooper { "a", a, __arraycount(a), 0 }, 9157718be8SEnji Cooper { "a/b", b, __arraycount(b), 0 }, 9257718be8SEnji Cooper }; 9357718be8SEnji Cooper 9457718be8SEnji Cooper static const char *glob_star[] = { 9557718be8SEnji Cooper "a/1", "a/3", "a/4", "a/b", "a/b/w", "a/b/x", "a/b/y", "a/b/z", 9657718be8SEnji Cooper }; 9757718be8SEnji Cooper 9857718be8SEnji Cooper static const char *glob_star_not[] = { 9957718be8SEnji Cooper "a/1", "a/3", "a/4", "a/b", 10057718be8SEnji Cooper }; 10157718be8SEnji Cooper 10257718be8SEnji Cooper static void 10357718be8SEnji Cooper trim(char *buf, size_t len, const char *name) 10457718be8SEnji Cooper { 10557718be8SEnji Cooper char *path = buf, *epath = buf + len; 10657718be8SEnji Cooper while (path < epath && (*path++ = *name++) != '\0') 10757718be8SEnji Cooper continue; 10857718be8SEnji Cooper path--; 10957718be8SEnji Cooper while (path > buf && *--path == '/') 11057718be8SEnji Cooper *path = '\0'; 11157718be8SEnji Cooper } 11257718be8SEnji Cooper 11357718be8SEnji Cooper static void * 11457718be8SEnji Cooper gl_opendir(const char *dir) 11557718be8SEnji Cooper { 11657718be8SEnji Cooper size_t i; 11757718be8SEnji Cooper char buf[MAXPATHLEN]; 11857718be8SEnji Cooper trim(buf, sizeof(buf), dir); 11957718be8SEnji Cooper 12057718be8SEnji Cooper for (i = 0; i < __arraycount(d); i++) 12157718be8SEnji Cooper if (strcmp(buf, d[i].name) == 0) { 12257718be8SEnji Cooper DPRINTF(("opendir %s %zu\n", buf, i)); 12357718be8SEnji Cooper return &d[i]; 12457718be8SEnji Cooper } 12557718be8SEnji Cooper errno = ENOENT; 12657718be8SEnji Cooper return NULL; 12757718be8SEnji Cooper } 12857718be8SEnji Cooper 12957718be8SEnji Cooper static struct dirent * 13057718be8SEnji Cooper gl_readdir(void *v) 13157718be8SEnji Cooper { 13257718be8SEnji Cooper static struct dirent dir; 13357718be8SEnji Cooper struct gl_dir *dd = v; 13457718be8SEnji Cooper if (dd->pos < dd->len) { 13557718be8SEnji Cooper const struct gl_file *f = &dd->dir[dd->pos++]; 13657718be8SEnji Cooper strcpy(dir.d_name, f->name); 13757718be8SEnji Cooper dir.d_namlen = strlen(f->name); 13857718be8SEnji Cooper dir.d_ino = dd->pos; 13957718be8SEnji Cooper dir.d_type = f->dir ? DT_DIR : DT_REG; 14057718be8SEnji Cooper DPRINTF(("readdir %s %d\n", dir.d_name, dir.d_type)); 141*8b8647bfSEnji Cooper #if defined(__FreeBSD__) 142*8b8647bfSEnji Cooper dir.d_reclen = -1; /* Does not have _DIRENT_RECLEN */ 143*8b8647bfSEnji Cooper #else 14457718be8SEnji Cooper dir.d_reclen = _DIRENT_RECLEN(&dir, dir.d_namlen); 145*8b8647bfSEnji Cooper #endif 14657718be8SEnji Cooper return &dir; 14757718be8SEnji Cooper } 14857718be8SEnji Cooper return NULL; 14957718be8SEnji Cooper } 15057718be8SEnji Cooper 15157718be8SEnji Cooper static int 15257718be8SEnji Cooper gl_stat(const char *name , __gl_stat_t *st) 15357718be8SEnji Cooper { 15457718be8SEnji Cooper char buf[MAXPATHLEN]; 15557718be8SEnji Cooper trim(buf, sizeof(buf), name); 15657718be8SEnji Cooper memset(st, 0, sizeof(*st)); 15757718be8SEnji Cooper 15857718be8SEnji Cooper if (strcmp(buf, "a") == 0 || strcmp(buf, "a/b") == 0) { 15957718be8SEnji Cooper st->st_mode |= _S_IFDIR; 16057718be8SEnji Cooper return 0; 16157718be8SEnji Cooper } 16257718be8SEnji Cooper 16357718be8SEnji Cooper if (buf[0] == 'a' && buf[1] == '/') { 16457718be8SEnji Cooper struct gl_file *f; 16557718be8SEnji Cooper size_t offs, count; 16657718be8SEnji Cooper 16757718be8SEnji Cooper if (buf[2] == 'b' && buf[3] == '/') { 16857718be8SEnji Cooper offs = 4; 16957718be8SEnji Cooper count = __arraycount(b); 17057718be8SEnji Cooper f = b; 17157718be8SEnji Cooper } else { 17257718be8SEnji Cooper offs = 2; 17357718be8SEnji Cooper count = __arraycount(a); 17457718be8SEnji Cooper f = a; 17557718be8SEnji Cooper } 17657718be8SEnji Cooper 17757718be8SEnji Cooper for (size_t i = 0; i < count; i++) 17857718be8SEnji Cooper if (strcmp(f[i].name, buf + offs) == 0) 17957718be8SEnji Cooper return 0; 18057718be8SEnji Cooper } 18157718be8SEnji Cooper DPRINTF(("stat %s %d\n", buf, st->st_mode)); 18257718be8SEnji Cooper errno = ENOENT; 18357718be8SEnji Cooper return -1; 18457718be8SEnji Cooper } 18557718be8SEnji Cooper 18657718be8SEnji Cooper static int 18757718be8SEnji Cooper gl_lstat(const char *name , __gl_stat_t *st) 18857718be8SEnji Cooper { 18957718be8SEnji Cooper return gl_stat(name, st); 19057718be8SEnji Cooper } 19157718be8SEnji Cooper 19257718be8SEnji Cooper static void 19357718be8SEnji Cooper gl_closedir(void *v) 19457718be8SEnji Cooper { 19557718be8SEnji Cooper struct gl_dir *dd = v; 19657718be8SEnji Cooper dd->pos = 0; 19757718be8SEnji Cooper DPRINTF(("closedir %p\n", dd)); 19857718be8SEnji Cooper } 19957718be8SEnji Cooper 20057718be8SEnji Cooper static void 20157718be8SEnji Cooper run(const char *p, int flags, const char **res, size_t len) 20257718be8SEnji Cooper { 20357718be8SEnji Cooper glob_t gl; 20457718be8SEnji Cooper size_t i; 20557718be8SEnji Cooper 20657718be8SEnji Cooper memset(&gl, 0, sizeof(gl)); 20757718be8SEnji Cooper gl.gl_opendir = gl_opendir; 20857718be8SEnji Cooper gl.gl_readdir = gl_readdir; 20957718be8SEnji Cooper gl.gl_closedir = gl_closedir; 21057718be8SEnji Cooper gl.gl_stat = gl_stat; 21157718be8SEnji Cooper gl.gl_lstat = gl_lstat; 21257718be8SEnji Cooper 21357718be8SEnji Cooper RZ(glob(p, GLOB_ALTDIRFUNC | flags, NULL, &gl)); 21457718be8SEnji Cooper 21557718be8SEnji Cooper for (i = 0; i < gl.gl_pathc; i++) 21657718be8SEnji Cooper DPRINTF(("%s\n", gl.gl_pathv[i])); 21757718be8SEnji Cooper 21857718be8SEnji Cooper ATF_CHECK(len == gl.gl_pathc); 21957718be8SEnji Cooper for (i = 0; i < gl.gl_pathc; i++) 22057718be8SEnji Cooper ATF_CHECK_STREQ(gl.gl_pathv[i], res[i]); 22157718be8SEnji Cooper 22257718be8SEnji Cooper globfree(&gl); 22357718be8SEnji Cooper } 22457718be8SEnji Cooper 22557718be8SEnji Cooper 226*8b8647bfSEnji Cooper #if !defined(__FreeBSD__) 22757718be8SEnji Cooper ATF_TC(glob_star); 22857718be8SEnji Cooper ATF_TC_HEAD(glob_star, tc) 22957718be8SEnji Cooper { 23057718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", 23157718be8SEnji Cooper "Test glob(3) ** with GLOB_STAR"); 23257718be8SEnji Cooper } 23357718be8SEnji Cooper 23457718be8SEnji Cooper ATF_TC_BODY(glob_star, tc) 23557718be8SEnji Cooper { 23657718be8SEnji Cooper run("a/**", GLOB_STAR, glob_star, __arraycount(glob_star)); 23757718be8SEnji Cooper } 238*8b8647bfSEnji Cooper #endif 23957718be8SEnji Cooper 24057718be8SEnji Cooper ATF_TC(glob_star_not); 24157718be8SEnji Cooper ATF_TC_HEAD(glob_star_not, tc) 24257718be8SEnji Cooper { 24357718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", 24457718be8SEnji Cooper "Test glob(3) ** without GLOB_STAR"); 24557718be8SEnji Cooper } 24657718be8SEnji Cooper 24757718be8SEnji Cooper 24857718be8SEnji Cooper ATF_TC_BODY(glob_star_not, tc) 24957718be8SEnji Cooper { 25057718be8SEnji Cooper run("a/**", 0, glob_star_not, __arraycount(glob_star_not)); 25157718be8SEnji Cooper } 25257718be8SEnji Cooper 25357718be8SEnji Cooper #if 0 25457718be8SEnji Cooper ATF_TC(glob_nocheck); 25557718be8SEnji Cooper ATF_TC_HEAD(glob_nocheck, tc) 25657718be8SEnji Cooper { 25757718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", 25857718be8SEnji Cooper "Test glob(3) pattern with backslash and GLOB_NOCHECK"); 25957718be8SEnji Cooper } 26057718be8SEnji Cooper 26157718be8SEnji Cooper 26257718be8SEnji Cooper ATF_TC_BODY(glob_nocheck, tc) 26357718be8SEnji Cooper { 26457718be8SEnji Cooper static const char pattern[] = { 'f', 'o', 'o', '\\', ';', 'b', 'a', 26557718be8SEnji Cooper 'r', '\0' }; 26657718be8SEnji Cooper static const char *glob_nocheck[] = { 26757718be8SEnji Cooper pattern 26857718be8SEnji Cooper }; 26957718be8SEnji Cooper run(pattern, GLOB_NOCHECK, glob_nocheck, __arraycount(glob_nocheck)); 27057718be8SEnji Cooper } 27157718be8SEnji Cooper #endif 27257718be8SEnji Cooper 27357718be8SEnji Cooper ATF_TP_ADD_TCS(tp) 27457718be8SEnji Cooper { 275*8b8647bfSEnji Cooper #if !defined(__FreeBSD__) 27657718be8SEnji Cooper ATF_TP_ADD_TC(tp, glob_star); 277*8b8647bfSEnji Cooper #endif 27857718be8SEnji Cooper ATF_TP_ADD_TC(tp, glob_star_not); 27957718be8SEnji Cooper /* 28057718be8SEnji Cooper * Remove this test for now - the GLOB_NOCHECK return value has been 28157718be8SEnji Cooper * re-defined to return a modified pattern in revision 1.33 of glob.c 28257718be8SEnji Cooper * 28357718be8SEnji Cooper * ATF_TP_ADD_TC(tp, glob_nocheck); 28457718be8SEnji Cooper */ 28557718be8SEnji Cooper 28657718be8SEnji Cooper return atf_no_error(); 28757718be8SEnji Cooper } 288