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 49ff0ba872SEnji Cooper #ifdef __FreeBSD__ 508b8647bfSEnji Cooper #include "h_macros.h" 518b8647bfSEnji Cooper #define __gl_stat_t struct stat 528b8647bfSEnji Cooper #define _S_IFDIR S_IFDIR 538b8647bfSEnji Cooper #else 5457718be8SEnji Cooper #include "../../../h_macros.h" 558b8647bfSEnji 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 94*c2546a21SEnji Cooper #ifndef __FreeBSD__ 9557718be8SEnji Cooper static const char *glob_star[] = { 9657718be8SEnji Cooper "a/1", "a/3", "a/4", "a/b", "a/b/w", "a/b/x", "a/b/y", "a/b/z", 9757718be8SEnji Cooper }; 98*c2546a21SEnji Cooper #endif 9957718be8SEnji Cooper 10057718be8SEnji Cooper static const char *glob_star_not[] = { 10157718be8SEnji Cooper "a/1", "a/3", "a/4", "a/b", 10257718be8SEnji Cooper }; 10357718be8SEnji Cooper 10457718be8SEnji Cooper static void 10557718be8SEnji Cooper trim(char *buf, size_t len, const char *name) 10657718be8SEnji Cooper { 10757718be8SEnji Cooper char *path = buf, *epath = buf + len; 10857718be8SEnji Cooper while (path < epath && (*path++ = *name++) != '\0') 10957718be8SEnji Cooper continue; 11057718be8SEnji Cooper path--; 11157718be8SEnji Cooper while (path > buf && *--path == '/') 11257718be8SEnji Cooper *path = '\0'; 11357718be8SEnji Cooper } 11457718be8SEnji Cooper 11557718be8SEnji Cooper static void * 11657718be8SEnji Cooper gl_opendir(const char *dir) 11757718be8SEnji Cooper { 11857718be8SEnji Cooper size_t i; 11957718be8SEnji Cooper char buf[MAXPATHLEN]; 12057718be8SEnji Cooper trim(buf, sizeof(buf), dir); 12157718be8SEnji Cooper 12257718be8SEnji Cooper for (i = 0; i < __arraycount(d); i++) 12357718be8SEnji Cooper if (strcmp(buf, d[i].name) == 0) { 12457718be8SEnji Cooper DPRINTF(("opendir %s %zu\n", buf, i)); 12557718be8SEnji Cooper return &d[i]; 12657718be8SEnji Cooper } 12757718be8SEnji Cooper errno = ENOENT; 12857718be8SEnji Cooper return NULL; 12957718be8SEnji Cooper } 13057718be8SEnji Cooper 13157718be8SEnji Cooper static struct dirent * 13257718be8SEnji Cooper gl_readdir(void *v) 13357718be8SEnji Cooper { 13457718be8SEnji Cooper static struct dirent dir; 13557718be8SEnji Cooper struct gl_dir *dd = v; 13657718be8SEnji Cooper if (dd->pos < dd->len) { 13757718be8SEnji Cooper const struct gl_file *f = &dd->dir[dd->pos++]; 13857718be8SEnji Cooper strcpy(dir.d_name, f->name); 13957718be8SEnji Cooper dir.d_namlen = strlen(f->name); 14057718be8SEnji Cooper dir.d_ino = dd->pos; 14157718be8SEnji Cooper dir.d_type = f->dir ? DT_DIR : DT_REG; 14257718be8SEnji Cooper DPRINTF(("readdir %s %d\n", dir.d_name, dir.d_type)); 143ff0ba872SEnji Cooper #ifdef __FreeBSD__ 1448b8647bfSEnji Cooper dir.d_reclen = -1; /* Does not have _DIRENT_RECLEN */ 1458b8647bfSEnji Cooper #else 14657718be8SEnji Cooper dir.d_reclen = _DIRENT_RECLEN(&dir, dir.d_namlen); 1478b8647bfSEnji Cooper #endif 14857718be8SEnji Cooper return &dir; 14957718be8SEnji Cooper } 15057718be8SEnji Cooper return NULL; 15157718be8SEnji Cooper } 15257718be8SEnji Cooper 15357718be8SEnji Cooper static int 15457718be8SEnji Cooper gl_stat(const char *name , __gl_stat_t *st) 15557718be8SEnji Cooper { 15657718be8SEnji Cooper char buf[MAXPATHLEN]; 15757718be8SEnji Cooper trim(buf, sizeof(buf), name); 15857718be8SEnji Cooper memset(st, 0, sizeof(*st)); 15957718be8SEnji Cooper 16057718be8SEnji Cooper if (strcmp(buf, "a") == 0 || strcmp(buf, "a/b") == 0) { 16157718be8SEnji Cooper st->st_mode |= _S_IFDIR; 16257718be8SEnji Cooper return 0; 16357718be8SEnji Cooper } 16457718be8SEnji Cooper 16557718be8SEnji Cooper if (buf[0] == 'a' && buf[1] == '/') { 16657718be8SEnji Cooper struct gl_file *f; 16757718be8SEnji Cooper size_t offs, count; 16857718be8SEnji Cooper 16957718be8SEnji Cooper if (buf[2] == 'b' && buf[3] == '/') { 17057718be8SEnji Cooper offs = 4; 17157718be8SEnji Cooper count = __arraycount(b); 17257718be8SEnji Cooper f = b; 17357718be8SEnji Cooper } else { 17457718be8SEnji Cooper offs = 2; 17557718be8SEnji Cooper count = __arraycount(a); 17657718be8SEnji Cooper f = a; 17757718be8SEnji Cooper } 17857718be8SEnji Cooper 17957718be8SEnji Cooper for (size_t i = 0; i < count; i++) 18057718be8SEnji Cooper if (strcmp(f[i].name, buf + offs) == 0) 18157718be8SEnji Cooper return 0; 18257718be8SEnji Cooper } 18357718be8SEnji Cooper DPRINTF(("stat %s %d\n", buf, st->st_mode)); 18457718be8SEnji Cooper errno = ENOENT; 18557718be8SEnji Cooper return -1; 18657718be8SEnji Cooper } 18757718be8SEnji Cooper 18857718be8SEnji Cooper static int 18957718be8SEnji Cooper gl_lstat(const char *name , __gl_stat_t *st) 19057718be8SEnji Cooper { 19157718be8SEnji Cooper return gl_stat(name, st); 19257718be8SEnji Cooper } 19357718be8SEnji Cooper 19457718be8SEnji Cooper static void 19557718be8SEnji Cooper gl_closedir(void *v) 19657718be8SEnji Cooper { 19757718be8SEnji Cooper struct gl_dir *dd = v; 19857718be8SEnji Cooper dd->pos = 0; 19957718be8SEnji Cooper DPRINTF(("closedir %p\n", dd)); 20057718be8SEnji Cooper } 20157718be8SEnji Cooper 20257718be8SEnji Cooper static void 20357718be8SEnji Cooper run(const char *p, int flags, const char **res, size_t len) 20457718be8SEnji Cooper { 20557718be8SEnji Cooper glob_t gl; 20657718be8SEnji Cooper size_t i; 20757718be8SEnji Cooper 20857718be8SEnji Cooper memset(&gl, 0, sizeof(gl)); 20957718be8SEnji Cooper gl.gl_opendir = gl_opendir; 21057718be8SEnji Cooper gl.gl_readdir = gl_readdir; 21157718be8SEnji Cooper gl.gl_closedir = gl_closedir; 21257718be8SEnji Cooper gl.gl_stat = gl_stat; 21357718be8SEnji Cooper gl.gl_lstat = gl_lstat; 21457718be8SEnji Cooper 21557718be8SEnji Cooper RZ(glob(p, GLOB_ALTDIRFUNC | flags, NULL, &gl)); 21657718be8SEnji Cooper 21757718be8SEnji Cooper for (i = 0; i < gl.gl_pathc; i++) 21857718be8SEnji Cooper DPRINTF(("%s\n", gl.gl_pathv[i])); 21957718be8SEnji Cooper 22057718be8SEnji Cooper ATF_CHECK(len == gl.gl_pathc); 22157718be8SEnji Cooper for (i = 0; i < gl.gl_pathc; i++) 22257718be8SEnji Cooper ATF_CHECK_STREQ(gl.gl_pathv[i], res[i]); 22357718be8SEnji Cooper 22457718be8SEnji Cooper globfree(&gl); 22557718be8SEnji Cooper } 22657718be8SEnji Cooper 22757718be8SEnji Cooper 228ff0ba872SEnji Cooper #ifndef __FreeBSD__ 22957718be8SEnji Cooper ATF_TC(glob_star); 23057718be8SEnji Cooper ATF_TC_HEAD(glob_star, tc) 23157718be8SEnji Cooper { 23257718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", 23357718be8SEnji Cooper "Test glob(3) ** with GLOB_STAR"); 23457718be8SEnji Cooper } 23557718be8SEnji Cooper 23657718be8SEnji Cooper ATF_TC_BODY(glob_star, tc) 23757718be8SEnji Cooper { 23857718be8SEnji Cooper run("a/**", GLOB_STAR, glob_star, __arraycount(glob_star)); 23957718be8SEnji Cooper } 2408b8647bfSEnji Cooper #endif 24157718be8SEnji Cooper 24257718be8SEnji Cooper ATF_TC(glob_star_not); 24357718be8SEnji Cooper ATF_TC_HEAD(glob_star_not, tc) 24457718be8SEnji Cooper { 24557718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", 24657718be8SEnji Cooper "Test glob(3) ** without GLOB_STAR"); 24757718be8SEnji Cooper } 24857718be8SEnji Cooper 24957718be8SEnji Cooper 25057718be8SEnji Cooper ATF_TC_BODY(glob_star_not, tc) 25157718be8SEnji Cooper { 25257718be8SEnji Cooper run("a/**", 0, glob_star_not, __arraycount(glob_star_not)); 25357718be8SEnji Cooper } 25457718be8SEnji Cooper 25557718be8SEnji Cooper #if 0 25657718be8SEnji Cooper ATF_TC(glob_nocheck); 25757718be8SEnji Cooper ATF_TC_HEAD(glob_nocheck, tc) 25857718be8SEnji Cooper { 25957718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", 26057718be8SEnji Cooper "Test glob(3) pattern with backslash and GLOB_NOCHECK"); 26157718be8SEnji Cooper } 26257718be8SEnji Cooper 26357718be8SEnji Cooper 26457718be8SEnji Cooper ATF_TC_BODY(glob_nocheck, tc) 26557718be8SEnji Cooper { 26657718be8SEnji Cooper static const char pattern[] = { 'f', 'o', 'o', '\\', ';', 'b', 'a', 26757718be8SEnji Cooper 'r', '\0' }; 26857718be8SEnji Cooper static const char *glob_nocheck[] = { 26957718be8SEnji Cooper pattern 27057718be8SEnji Cooper }; 27157718be8SEnji Cooper run(pattern, GLOB_NOCHECK, glob_nocheck, __arraycount(glob_nocheck)); 27257718be8SEnji Cooper } 27357718be8SEnji Cooper #endif 27457718be8SEnji Cooper 27557718be8SEnji Cooper ATF_TP_ADD_TCS(tp) 27657718be8SEnji Cooper { 277ff0ba872SEnji Cooper #ifndef __FreeBSD__ 27857718be8SEnji Cooper ATF_TP_ADD_TC(tp, glob_star); 2798b8647bfSEnji Cooper #endif 28057718be8SEnji Cooper ATF_TP_ADD_TC(tp, glob_star_not); 28157718be8SEnji Cooper /* 28257718be8SEnji Cooper * Remove this test for now - the GLOB_NOCHECK return value has been 28357718be8SEnji Cooper * re-defined to return a modified pattern in revision 1.33 of glob.c 28457718be8SEnji Cooper * 28557718be8SEnji Cooper * ATF_TP_ADD_TC(tp, glob_nocheck); 28657718be8SEnji Cooper */ 28757718be8SEnji Cooper 28857718be8SEnji Cooper return atf_no_error(); 28957718be8SEnji Cooper } 290