xref: /freebsd/contrib/netbsd-tests/lib/libc/gen/t_glob.c (revision 1a36faad54665288ed4eb839d2a4699ae2ead45e)
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