xref: /freebsd-src/contrib/netbsd-tests/lib/libc/gen/t_glob.c (revision 57718be8fa0bd5edc11ab9a72e68cc71982939a6)
1*57718be8SEnji Cooper /*	$NetBSD: t_glob.c,v 1.3 2013/01/02 11:28:48 martin Exp $	*/
2*57718be8SEnji Cooper /*-
3*57718be8SEnji Cooper  * Copyright (c) 2010 The NetBSD Foundation, Inc.
4*57718be8SEnji Cooper  * All rights reserved.
5*57718be8SEnji Cooper  *
6*57718be8SEnji Cooper  * This code is derived from software contributed to The NetBSD Foundation
7*57718be8SEnji Cooper  * by Christos Zoulas
8*57718be8SEnji Cooper  *
9*57718be8SEnji Cooper  * Redistribution and use in source and binary forms, with or without
10*57718be8SEnji Cooper  * modification, are permitted provided that the following conditions
11*57718be8SEnji Cooper  * are met:
12*57718be8SEnji Cooper  *
13*57718be8SEnji Cooper  * 1. Redistributions of source code must retain the above copyright
14*57718be8SEnji Cooper  *    notice, this list of conditions and the following disclaimer.
15*57718be8SEnji Cooper  * 2. Redistributions in binary form must reproduce the above copyright
16*57718be8SEnji Cooper  *    notice, this list of conditions and the following disclaimer in
17*57718be8SEnji Cooper  *    the documentation and/or other materials provided with the
18*57718be8SEnji Cooper  *    distribution.
19*57718be8SEnji Cooper  *
20*57718be8SEnji Cooper  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21*57718be8SEnji Cooper  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*57718be8SEnji Cooper  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23*57718be8SEnji Cooper  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
24*57718be8SEnji Cooper  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25*57718be8SEnji Cooper  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
26*57718be8SEnji Cooper  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27*57718be8SEnji Cooper  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28*57718be8SEnji Cooper  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29*57718be8SEnji Cooper  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30*57718be8SEnji Cooper  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31*57718be8SEnji Cooper  * SUCH DAMAGE.
32*57718be8SEnji Cooper  */
33*57718be8SEnji Cooper 
34*57718be8SEnji Cooper #include <sys/cdefs.h>
35*57718be8SEnji Cooper __RCSID("$NetBSD: t_glob.c,v 1.3 2013/01/02 11:28:48 martin Exp $");
36*57718be8SEnji Cooper 
37*57718be8SEnji Cooper #include <atf-c.h>
38*57718be8SEnji Cooper 
39*57718be8SEnji Cooper #include <sys/param.h>
40*57718be8SEnji Cooper #include <sys/stat.h>
41*57718be8SEnji Cooper 
42*57718be8SEnji Cooper #include <dirent.h>
43*57718be8SEnji Cooper #include <glob.h>
44*57718be8SEnji Cooper #include <stdio.h>
45*57718be8SEnji Cooper #include <stdlib.h>
46*57718be8SEnji Cooper #include <string.h>
47*57718be8SEnji Cooper #include <errno.h>
48*57718be8SEnji Cooper 
49*57718be8SEnji Cooper #include "../../../h_macros.h"
50*57718be8SEnji Cooper 
51*57718be8SEnji Cooper 
52*57718be8SEnji Cooper #ifdef DEBUG
53*57718be8SEnji Cooper #define DPRINTF(a) printf a
54*57718be8SEnji Cooper #else
55*57718be8SEnji Cooper #define DPRINTF(a)
56*57718be8SEnji Cooper #endif
57*57718be8SEnji Cooper 
58*57718be8SEnji Cooper struct gl_file {
59*57718be8SEnji Cooper 	const char *name;
60*57718be8SEnji Cooper 	int dir;
61*57718be8SEnji Cooper };
62*57718be8SEnji Cooper 
63*57718be8SEnji Cooper static struct gl_file a[] = {
64*57718be8SEnji Cooper 	{ "1", 0 },
65*57718be8SEnji Cooper 	{ "b", 1 },
66*57718be8SEnji Cooper 	{ "3", 0 },
67*57718be8SEnji Cooper 	{ "4", 0 },
68*57718be8SEnji Cooper };
69*57718be8SEnji Cooper 
70*57718be8SEnji Cooper static struct gl_file b[] = {
71*57718be8SEnji Cooper 	{ "x", 0 },
72*57718be8SEnji Cooper 	{ "y", 0 },
73*57718be8SEnji Cooper 	{ "z", 0 },
74*57718be8SEnji Cooper 	{ "w", 0 },
75*57718be8SEnji Cooper };
76*57718be8SEnji Cooper 
77*57718be8SEnji Cooper struct gl_dir {
78*57718be8SEnji Cooper 	const char *name;	/* directory name */
79*57718be8SEnji Cooper 	const struct gl_file *dir;
80*57718be8SEnji Cooper 	size_t len, pos;
81*57718be8SEnji Cooper };
82*57718be8SEnji Cooper 
83*57718be8SEnji Cooper static struct gl_dir d[] = {
84*57718be8SEnji Cooper 	{ "a", a, __arraycount(a), 0 },
85*57718be8SEnji Cooper 	{ "a/b", b, __arraycount(b), 0 },
86*57718be8SEnji Cooper };
87*57718be8SEnji Cooper 
88*57718be8SEnji Cooper static const char *glob_star[] = {
89*57718be8SEnji Cooper     "a/1", "a/3", "a/4", "a/b", "a/b/w", "a/b/x", "a/b/y", "a/b/z",
90*57718be8SEnji Cooper };
91*57718be8SEnji Cooper 
92*57718be8SEnji Cooper static const char *glob_star_not[] = {
93*57718be8SEnji Cooper 	"a/1", "a/3", "a/4", "a/b",
94*57718be8SEnji Cooper };
95*57718be8SEnji Cooper 
96*57718be8SEnji Cooper static void
97*57718be8SEnji Cooper trim(char *buf, size_t len, const char *name)
98*57718be8SEnji Cooper {
99*57718be8SEnji Cooper 	char *path = buf, *epath = buf + len;
100*57718be8SEnji Cooper 	while (path < epath && (*path++ = *name++) != '\0')
101*57718be8SEnji Cooper 		continue;
102*57718be8SEnji Cooper 	path--;
103*57718be8SEnji Cooper 	while (path > buf && *--path == '/')
104*57718be8SEnji Cooper 		*path = '\0';
105*57718be8SEnji Cooper }
106*57718be8SEnji Cooper 
107*57718be8SEnji Cooper static void *
108*57718be8SEnji Cooper gl_opendir(const char *dir)
109*57718be8SEnji Cooper {
110*57718be8SEnji Cooper 	size_t i;
111*57718be8SEnji Cooper 	char buf[MAXPATHLEN];
112*57718be8SEnji Cooper 	trim(buf, sizeof(buf), dir);
113*57718be8SEnji Cooper 
114*57718be8SEnji Cooper 	for (i = 0; i < __arraycount(d); i++)
115*57718be8SEnji Cooper 		if (strcmp(buf, d[i].name) == 0) {
116*57718be8SEnji Cooper 			DPRINTF(("opendir %s %zu\n", buf, i));
117*57718be8SEnji Cooper 			return &d[i];
118*57718be8SEnji Cooper 		}
119*57718be8SEnji Cooper 	errno = ENOENT;
120*57718be8SEnji Cooper 	return NULL;
121*57718be8SEnji Cooper }
122*57718be8SEnji Cooper 
123*57718be8SEnji Cooper static struct dirent *
124*57718be8SEnji Cooper gl_readdir(void *v)
125*57718be8SEnji Cooper {
126*57718be8SEnji Cooper 	static struct dirent dir;
127*57718be8SEnji Cooper 	struct gl_dir *dd = v;
128*57718be8SEnji Cooper 	if (dd->pos < dd->len) {
129*57718be8SEnji Cooper 		const struct gl_file *f = &dd->dir[dd->pos++];
130*57718be8SEnji Cooper 		strcpy(dir.d_name, f->name);
131*57718be8SEnji Cooper 		dir.d_namlen = strlen(f->name);
132*57718be8SEnji Cooper 		dir.d_ino = dd->pos;
133*57718be8SEnji Cooper 		dir.d_type = f->dir ? DT_DIR : DT_REG;
134*57718be8SEnji Cooper 		DPRINTF(("readdir %s %d\n", dir.d_name, dir.d_type));
135*57718be8SEnji Cooper 		dir.d_reclen = _DIRENT_RECLEN(&dir, dir.d_namlen);
136*57718be8SEnji Cooper 		return &dir;
137*57718be8SEnji Cooper 	}
138*57718be8SEnji Cooper 	return NULL;
139*57718be8SEnji Cooper }
140*57718be8SEnji Cooper 
141*57718be8SEnji Cooper static int
142*57718be8SEnji Cooper gl_stat(const char *name , __gl_stat_t *st)
143*57718be8SEnji Cooper {
144*57718be8SEnji Cooper 	char buf[MAXPATHLEN];
145*57718be8SEnji Cooper 	trim(buf, sizeof(buf), name);
146*57718be8SEnji Cooper 	memset(st, 0, sizeof(*st));
147*57718be8SEnji Cooper 
148*57718be8SEnji Cooper 	if (strcmp(buf, "a") == 0 || strcmp(buf, "a/b") == 0) {
149*57718be8SEnji Cooper 		st->st_mode |= _S_IFDIR;
150*57718be8SEnji Cooper 		return 0;
151*57718be8SEnji Cooper 	}
152*57718be8SEnji Cooper 
153*57718be8SEnji Cooper 	if (buf[0] == 'a' && buf[1] == '/') {
154*57718be8SEnji Cooper 		struct gl_file *f;
155*57718be8SEnji Cooper 		size_t offs, count;
156*57718be8SEnji Cooper 
157*57718be8SEnji Cooper 		if (buf[2] == 'b' && buf[3] == '/') {
158*57718be8SEnji Cooper 			offs = 4;
159*57718be8SEnji Cooper 			count = __arraycount(b);
160*57718be8SEnji Cooper 			f = b;
161*57718be8SEnji Cooper 		} else {
162*57718be8SEnji Cooper 			offs = 2;
163*57718be8SEnji Cooper 			count = __arraycount(a);
164*57718be8SEnji Cooper 			f = a;
165*57718be8SEnji Cooper 		}
166*57718be8SEnji Cooper 
167*57718be8SEnji Cooper 		for (size_t i = 0; i < count; i++)
168*57718be8SEnji Cooper 			if (strcmp(f[i].name, buf + offs) == 0)
169*57718be8SEnji Cooper 				return 0;
170*57718be8SEnji Cooper 	}
171*57718be8SEnji Cooper 	DPRINTF(("stat %s %d\n", buf, st->st_mode));
172*57718be8SEnji Cooper 	errno = ENOENT;
173*57718be8SEnji Cooper 	return -1;
174*57718be8SEnji Cooper }
175*57718be8SEnji Cooper 
176*57718be8SEnji Cooper static int
177*57718be8SEnji Cooper gl_lstat(const char *name , __gl_stat_t *st)
178*57718be8SEnji Cooper {
179*57718be8SEnji Cooper 	return gl_stat(name, st);
180*57718be8SEnji Cooper }
181*57718be8SEnji Cooper 
182*57718be8SEnji Cooper static void
183*57718be8SEnji Cooper gl_closedir(void *v)
184*57718be8SEnji Cooper {
185*57718be8SEnji Cooper 	struct gl_dir *dd = v;
186*57718be8SEnji Cooper 	dd->pos = 0;
187*57718be8SEnji Cooper 	DPRINTF(("closedir %p\n", dd));
188*57718be8SEnji Cooper }
189*57718be8SEnji Cooper 
190*57718be8SEnji Cooper static void
191*57718be8SEnji Cooper run(const char *p, int flags, const char **res, size_t len)
192*57718be8SEnji Cooper {
193*57718be8SEnji Cooper 	glob_t gl;
194*57718be8SEnji Cooper 	size_t i;
195*57718be8SEnji Cooper 
196*57718be8SEnji Cooper 	memset(&gl, 0, sizeof(gl));
197*57718be8SEnji Cooper 	gl.gl_opendir = gl_opendir;
198*57718be8SEnji Cooper 	gl.gl_readdir = gl_readdir;
199*57718be8SEnji Cooper 	gl.gl_closedir = gl_closedir;
200*57718be8SEnji Cooper 	gl.gl_stat = gl_stat;
201*57718be8SEnji Cooper 	gl.gl_lstat = gl_lstat;
202*57718be8SEnji Cooper 
203*57718be8SEnji Cooper 	RZ(glob(p, GLOB_ALTDIRFUNC | flags, NULL, &gl));
204*57718be8SEnji Cooper 
205*57718be8SEnji Cooper 	for (i = 0; i < gl.gl_pathc; i++)
206*57718be8SEnji Cooper 		DPRINTF(("%s\n", gl.gl_pathv[i]));
207*57718be8SEnji Cooper 
208*57718be8SEnji Cooper 	ATF_CHECK(len == gl.gl_pathc);
209*57718be8SEnji Cooper 	for (i = 0; i < gl.gl_pathc; i++)
210*57718be8SEnji Cooper 		ATF_CHECK_STREQ(gl.gl_pathv[i], res[i]);
211*57718be8SEnji Cooper 
212*57718be8SEnji Cooper 	globfree(&gl);
213*57718be8SEnji Cooper }
214*57718be8SEnji Cooper 
215*57718be8SEnji Cooper 
216*57718be8SEnji Cooper ATF_TC(glob_star);
217*57718be8SEnji Cooper ATF_TC_HEAD(glob_star, tc)
218*57718be8SEnji Cooper {
219*57718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
220*57718be8SEnji Cooper 	    "Test glob(3) ** with GLOB_STAR");
221*57718be8SEnji Cooper }
222*57718be8SEnji Cooper 
223*57718be8SEnji Cooper ATF_TC_BODY(glob_star, tc)
224*57718be8SEnji Cooper {
225*57718be8SEnji Cooper 	run("a/**", GLOB_STAR, glob_star, __arraycount(glob_star));
226*57718be8SEnji Cooper }
227*57718be8SEnji Cooper 
228*57718be8SEnji Cooper ATF_TC(glob_star_not);
229*57718be8SEnji Cooper ATF_TC_HEAD(glob_star_not, tc)
230*57718be8SEnji Cooper {
231*57718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
232*57718be8SEnji Cooper 	    "Test glob(3) ** without GLOB_STAR");
233*57718be8SEnji Cooper }
234*57718be8SEnji Cooper 
235*57718be8SEnji Cooper 
236*57718be8SEnji Cooper ATF_TC_BODY(glob_star_not, tc)
237*57718be8SEnji Cooper {
238*57718be8SEnji Cooper 	run("a/**", 0, glob_star_not, __arraycount(glob_star_not));
239*57718be8SEnji Cooper }
240*57718be8SEnji Cooper 
241*57718be8SEnji Cooper #if 0
242*57718be8SEnji Cooper ATF_TC(glob_nocheck);
243*57718be8SEnji Cooper ATF_TC_HEAD(glob_nocheck, tc)
244*57718be8SEnji Cooper {
245*57718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
246*57718be8SEnji Cooper 	    "Test glob(3) pattern with backslash and GLOB_NOCHECK");
247*57718be8SEnji Cooper }
248*57718be8SEnji Cooper 
249*57718be8SEnji Cooper 
250*57718be8SEnji Cooper ATF_TC_BODY(glob_nocheck, tc)
251*57718be8SEnji Cooper {
252*57718be8SEnji Cooper 	static const char pattern[] = { 'f', 'o', 'o', '\\', ';', 'b', 'a',
253*57718be8SEnji Cooper 	    'r', '\0' };
254*57718be8SEnji Cooper 	static const char *glob_nocheck[] = {
255*57718be8SEnji Cooper 	    pattern
256*57718be8SEnji Cooper 	};
257*57718be8SEnji Cooper 	run(pattern, GLOB_NOCHECK, glob_nocheck, __arraycount(glob_nocheck));
258*57718be8SEnji Cooper }
259*57718be8SEnji Cooper #endif
260*57718be8SEnji Cooper 
261*57718be8SEnji Cooper ATF_TP_ADD_TCS(tp)
262*57718be8SEnji Cooper {
263*57718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, glob_star);
264*57718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, glob_star_not);
265*57718be8SEnji Cooper /*
266*57718be8SEnji Cooper  * Remove this test for now - the GLOB_NOCHECK return value has been
267*57718be8SEnji Cooper  * re-defined to return a modified pattern in revision 1.33 of glob.c
268*57718be8SEnji Cooper  *
269*57718be8SEnji Cooper  *	ATF_TP_ADD_TC(tp, glob_nocheck);
270*57718be8SEnji Cooper  */
271*57718be8SEnji Cooper 
272*57718be8SEnji Cooper 	return atf_no_error();
273*57718be8SEnji Cooper }
274