1f40f3adcSEnji Cooper /* $NetBSD: t_glob.c,v 1.5 2017/01/14 20:47:41 christos 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>
35f40f3adcSEnji Cooper __RCSID("$NetBSD: t_glob.c,v 1.5 2017/01/14 20:47:41 christos 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
498b8647bfSEnji Cooper #include "h_macros.h"
5063d1fd59SEnji Cooper
5157718be8SEnji Cooper
5257718be8SEnji Cooper #ifdef DEBUG
5357718be8SEnji Cooper #define DPRINTF(a) printf a
5457718be8SEnji Cooper #else
5557718be8SEnji Cooper #define DPRINTF(a)
5657718be8SEnji Cooper #endif
5757718be8SEnji Cooper
5857718be8SEnji Cooper struct gl_file {
5957718be8SEnji Cooper const char *name;
6057718be8SEnji Cooper int dir;
6157718be8SEnji Cooper };
6257718be8SEnji Cooper
6357718be8SEnji Cooper static struct gl_file a[] = {
6457718be8SEnji Cooper { "1", 0 },
6557718be8SEnji Cooper { "b", 1 },
6657718be8SEnji Cooper { "3", 0 },
6757718be8SEnji Cooper { "4", 0 },
6857718be8SEnji Cooper };
6957718be8SEnji Cooper
7057718be8SEnji Cooper static struct gl_file b[] = {
7157718be8SEnji Cooper { "x", 0 },
7257718be8SEnji Cooper { "y", 0 },
7357718be8SEnji Cooper { "z", 0 },
7457718be8SEnji Cooper { "w", 0 },
7557718be8SEnji Cooper };
7657718be8SEnji Cooper
7757718be8SEnji Cooper struct gl_dir {
7857718be8SEnji Cooper const char *name; /* directory name */
7957718be8SEnji Cooper const struct gl_file *dir;
8057718be8SEnji Cooper size_t len, pos;
8157718be8SEnji Cooper };
8257718be8SEnji Cooper
8357718be8SEnji Cooper static struct gl_dir d[] = {
8457718be8SEnji Cooper { "a", a, __arraycount(a), 0 },
8557718be8SEnji Cooper { "a/b", b, __arraycount(b), 0 },
8657718be8SEnji Cooper };
8757718be8SEnji Cooper
88*89964aabSEnji Cooper #ifdef GLOB_STAR
8957718be8SEnji Cooper static const char *glob_star[] = {
9057718be8SEnji Cooper "a/1", "a/3", "a/4", "a/b", "a/b/w", "a/b/x", "a/b/y", "a/b/z",
9157718be8SEnji Cooper };
92c2546a21SEnji Cooper #endif
9357718be8SEnji Cooper
9457718be8SEnji Cooper static const char *glob_star_not[] = {
9557718be8SEnji Cooper "a/1", "a/3", "a/4", "a/b",
9657718be8SEnji Cooper };
9757718be8SEnji Cooper
9857718be8SEnji Cooper static void
trim(char * buf,size_t len,const char * name)9957718be8SEnji Cooper trim(char *buf, size_t len, const char *name)
10057718be8SEnji Cooper {
10157718be8SEnji Cooper char *path = buf, *epath = buf + len;
10257718be8SEnji Cooper while (path < epath && (*path++ = *name++) != '\0')
10357718be8SEnji Cooper continue;
10457718be8SEnji Cooper path--;
10557718be8SEnji Cooper while (path > buf && *--path == '/')
10657718be8SEnji Cooper *path = '\0';
10757718be8SEnji Cooper }
10857718be8SEnji Cooper
10957718be8SEnji Cooper static void *
gl_opendir(const char * dir)11057718be8SEnji Cooper gl_opendir(const char *dir)
11157718be8SEnji Cooper {
11257718be8SEnji Cooper size_t i;
11357718be8SEnji Cooper char buf[MAXPATHLEN];
11457718be8SEnji Cooper trim(buf, sizeof(buf), dir);
11557718be8SEnji Cooper
11657718be8SEnji Cooper for (i = 0; i < __arraycount(d); i++)
11757718be8SEnji Cooper if (strcmp(buf, d[i].name) == 0) {
11857718be8SEnji Cooper DPRINTF(("opendir %s %zu\n", buf, i));
11957718be8SEnji Cooper return &d[i];
12057718be8SEnji Cooper }
12157718be8SEnji Cooper errno = ENOENT;
12257718be8SEnji Cooper return NULL;
12357718be8SEnji Cooper }
12457718be8SEnji Cooper
12557718be8SEnji Cooper static struct dirent *
gl_readdir(void * v)12657718be8SEnji Cooper gl_readdir(void *v)
12757718be8SEnji Cooper {
12857718be8SEnji Cooper static struct dirent dir;
12957718be8SEnji Cooper struct gl_dir *dd = v;
13057718be8SEnji Cooper if (dd->pos < dd->len) {
13157718be8SEnji Cooper const struct gl_file *f = &dd->dir[dd->pos++];
13257718be8SEnji Cooper strcpy(dir.d_name, f->name);
13357718be8SEnji Cooper dir.d_namlen = strlen(f->name);
13457718be8SEnji Cooper dir.d_ino = dd->pos;
13557718be8SEnji Cooper dir.d_type = f->dir ? DT_DIR : DT_REG;
13657718be8SEnji Cooper DPRINTF(("readdir %s %d\n", dir.d_name, dir.d_type));
137ff0ba872SEnji Cooper #ifdef __FreeBSD__
1388b8647bfSEnji Cooper dir.d_reclen = -1; /* Does not have _DIRENT_RECLEN */
1398b8647bfSEnji Cooper #else
14057718be8SEnji Cooper dir.d_reclen = _DIRENT_RECLEN(&dir, dir.d_namlen);
1418b8647bfSEnji Cooper #endif
14257718be8SEnji Cooper return &dir;
14357718be8SEnji Cooper }
14457718be8SEnji Cooper return NULL;
14557718be8SEnji Cooper }
14657718be8SEnji Cooper
14757718be8SEnji Cooper static int
gl_stat(const char * name,__gl_stat_t * st)14857718be8SEnji Cooper gl_stat(const char *name , __gl_stat_t *st)
14957718be8SEnji Cooper {
15057718be8SEnji Cooper char buf[MAXPATHLEN];
15157718be8SEnji Cooper trim(buf, sizeof(buf), name);
15257718be8SEnji Cooper memset(st, 0, sizeof(*st));
15357718be8SEnji Cooper
15457718be8SEnji Cooper if (strcmp(buf, "a") == 0 || strcmp(buf, "a/b") == 0) {
155f40f3adcSEnji Cooper st->st_mode |= S_IFDIR;
15657718be8SEnji Cooper return 0;
15757718be8SEnji Cooper }
15857718be8SEnji Cooper
15957718be8SEnji Cooper if (buf[0] == 'a' && buf[1] == '/') {
16057718be8SEnji Cooper struct gl_file *f;
16157718be8SEnji Cooper size_t offs, count;
16257718be8SEnji Cooper
16357718be8SEnji Cooper if (buf[2] == 'b' && buf[3] == '/') {
16457718be8SEnji Cooper offs = 4;
16557718be8SEnji Cooper count = __arraycount(b);
16657718be8SEnji Cooper f = b;
16757718be8SEnji Cooper } else {
16857718be8SEnji Cooper offs = 2;
16957718be8SEnji Cooper count = __arraycount(a);
17057718be8SEnji Cooper f = a;
17157718be8SEnji Cooper }
17257718be8SEnji Cooper
17357718be8SEnji Cooper for (size_t i = 0; i < count; i++)
17457718be8SEnji Cooper if (strcmp(f[i].name, buf + offs) == 0)
17557718be8SEnji Cooper return 0;
17657718be8SEnji Cooper }
17757718be8SEnji Cooper DPRINTF(("stat %s %d\n", buf, st->st_mode));
17857718be8SEnji Cooper errno = ENOENT;
17957718be8SEnji Cooper return -1;
18057718be8SEnji Cooper }
18157718be8SEnji Cooper
18257718be8SEnji Cooper static int
gl_lstat(const char * name,__gl_stat_t * st)18357718be8SEnji Cooper gl_lstat(const char *name , __gl_stat_t *st)
18457718be8SEnji Cooper {
18557718be8SEnji Cooper return gl_stat(name, st);
18657718be8SEnji Cooper }
18757718be8SEnji Cooper
18857718be8SEnji Cooper static void
gl_closedir(void * v)18957718be8SEnji Cooper gl_closedir(void *v)
19057718be8SEnji Cooper {
19157718be8SEnji Cooper struct gl_dir *dd = v;
19257718be8SEnji Cooper dd->pos = 0;
19357718be8SEnji Cooper DPRINTF(("closedir %p\n", dd));
19457718be8SEnji Cooper }
19557718be8SEnji Cooper
19657718be8SEnji Cooper static void
run(const char * p,int flags,const char ** res,size_t len)19757718be8SEnji Cooper run(const char *p, int flags, const char **res, size_t len)
19857718be8SEnji Cooper {
19957718be8SEnji Cooper glob_t gl;
20057718be8SEnji Cooper size_t i;
20157718be8SEnji Cooper
20257718be8SEnji Cooper memset(&gl, 0, sizeof(gl));
20357718be8SEnji Cooper gl.gl_opendir = gl_opendir;
20457718be8SEnji Cooper gl.gl_readdir = gl_readdir;
20557718be8SEnji Cooper gl.gl_closedir = gl_closedir;
20657718be8SEnji Cooper gl.gl_stat = gl_stat;
20757718be8SEnji Cooper gl.gl_lstat = gl_lstat;
20857718be8SEnji Cooper
20957718be8SEnji Cooper RZ(glob(p, GLOB_ALTDIRFUNC | flags, NULL, &gl));
21057718be8SEnji Cooper
21157718be8SEnji Cooper for (i = 0; i < gl.gl_pathc; i++)
21257718be8SEnji Cooper DPRINTF(("%s\n", gl.gl_pathv[i]));
21357718be8SEnji Cooper
21457718be8SEnji Cooper ATF_CHECK(len == gl.gl_pathc);
21557718be8SEnji Cooper for (i = 0; i < gl.gl_pathc; i++)
21657718be8SEnji Cooper ATF_CHECK_STREQ(gl.gl_pathv[i], res[i]);
21757718be8SEnji Cooper
21857718be8SEnji Cooper globfree(&gl);
21957718be8SEnji Cooper }
22057718be8SEnji Cooper
22157718be8SEnji Cooper
222*89964aabSEnji Cooper #ifdef GLOB_STAR
22357718be8SEnji Cooper ATF_TC(glob_star);
ATF_TC_HEAD(glob_star,tc)22457718be8SEnji Cooper ATF_TC_HEAD(glob_star, tc)
22557718be8SEnji Cooper {
22657718be8SEnji Cooper atf_tc_set_md_var(tc, "descr",
22757718be8SEnji Cooper "Test glob(3) ** with GLOB_STAR");
22857718be8SEnji Cooper }
22957718be8SEnji Cooper
ATF_TC_BODY(glob_star,tc)23057718be8SEnji Cooper ATF_TC_BODY(glob_star, tc)
23157718be8SEnji Cooper {
23257718be8SEnji Cooper run("a/**", GLOB_STAR, glob_star, __arraycount(glob_star));
23357718be8SEnji Cooper }
2348b8647bfSEnji Cooper #endif
23557718be8SEnji Cooper
23657718be8SEnji Cooper ATF_TC(glob_star_not);
ATF_TC_HEAD(glob_star_not,tc)23757718be8SEnji Cooper ATF_TC_HEAD(glob_star_not, tc)
23857718be8SEnji Cooper {
23957718be8SEnji Cooper atf_tc_set_md_var(tc, "descr",
24057718be8SEnji Cooper "Test glob(3) ** without GLOB_STAR");
24157718be8SEnji Cooper }
24257718be8SEnji Cooper
24357718be8SEnji Cooper
ATF_TC_BODY(glob_star_not,tc)24457718be8SEnji Cooper ATF_TC_BODY(glob_star_not, tc)
24557718be8SEnji Cooper {
24657718be8SEnji Cooper run("a/**", 0, glob_star_not, __arraycount(glob_star_not));
24757718be8SEnji Cooper }
24857718be8SEnji Cooper
24957718be8SEnji Cooper #if 0
25057718be8SEnji Cooper ATF_TC(glob_nocheck);
25157718be8SEnji Cooper ATF_TC_HEAD(glob_nocheck, tc)
25257718be8SEnji Cooper {
25357718be8SEnji Cooper atf_tc_set_md_var(tc, "descr",
25457718be8SEnji Cooper "Test glob(3) pattern with backslash and GLOB_NOCHECK");
25557718be8SEnji Cooper }
25657718be8SEnji Cooper
25757718be8SEnji Cooper
25857718be8SEnji Cooper ATF_TC_BODY(glob_nocheck, tc)
25957718be8SEnji Cooper {
26057718be8SEnji Cooper static const char pattern[] = { 'f', 'o', 'o', '\\', ';', 'b', 'a',
26157718be8SEnji Cooper 'r', '\0' };
26257718be8SEnji Cooper static const char *glob_nocheck[] = {
26357718be8SEnji Cooper pattern
26457718be8SEnji Cooper };
26557718be8SEnji Cooper run(pattern, GLOB_NOCHECK, glob_nocheck, __arraycount(glob_nocheck));
26657718be8SEnji Cooper }
26757718be8SEnji Cooper #endif
26857718be8SEnji Cooper
ATF_TP_ADD_TCS(tp)26957718be8SEnji Cooper ATF_TP_ADD_TCS(tp)
27057718be8SEnji Cooper {
271*89964aabSEnji Cooper #ifdef GLOB_STAR
27257718be8SEnji Cooper ATF_TP_ADD_TC(tp, glob_star);
2738b8647bfSEnji Cooper #endif
27457718be8SEnji Cooper ATF_TP_ADD_TC(tp, glob_star_not);
27557718be8SEnji Cooper /*
27657718be8SEnji Cooper * Remove this test for now - the GLOB_NOCHECK return value has been
27757718be8SEnji Cooper * re-defined to return a modified pattern in revision 1.33 of glob.c
27857718be8SEnji Cooper *
27957718be8SEnji Cooper * ATF_TP_ADD_TC(tp, glob_nocheck);
28057718be8SEnji Cooper */
28157718be8SEnji Cooper
28257718be8SEnji Cooper return atf_no_error();
28357718be8SEnji Cooper }
284