1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1985-2011 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12da2e3ebdSchin *                                                                      *
13da2e3ebdSchin *              Information and Software Systems Research               *
14da2e3ebdSchin *                            AT&T Research                             *
15da2e3ebdSchin *                           Florham Park NJ                            *
16da2e3ebdSchin *                                                                      *
17da2e3ebdSchin *                 Glenn Fowler <gsf@research.att.com>                  *
18da2e3ebdSchin *                  David Korn <dgk@research.att.com>                   *
19da2e3ebdSchin *                   Phong Vo <kpv@research.att.com>                    *
20da2e3ebdSchin *                                                                      *
21da2e3ebdSchin ***********************************************************************/
22da2e3ebdSchin #pragma prototyped
23da2e3ebdSchin /*
24da2e3ebdSchin  * Glenn Fowler
25da2e3ebdSchin  * AT&T Research
26da2e3ebdSchin  *
27da2e3ebdSchin  * ftwalk on top of fts
28da2e3ebdSchin  */
29da2e3ebdSchin 
30da2e3ebdSchin #include <ast.h>
31da2e3ebdSchin #include <ftwalk.h>
32da2e3ebdSchin 
33da2e3ebdSchin static struct
34da2e3ebdSchin {
35da2e3ebdSchin 	int	(*comparf)(Ftw_t*, Ftw_t*);
36da2e3ebdSchin } state;
37da2e3ebdSchin 
38da2e3ebdSchin /*
39da2e3ebdSchin  * why does fts take FTSENT** instead of FTSENT*
40da2e3ebdSchin  */
41da2e3ebdSchin 
42da2e3ebdSchin static int
ftscompare(Ftw_t * const * pf1,Ftw_t * const * pf2)43da2e3ebdSchin ftscompare(Ftw_t* const* pf1, Ftw_t* const* pf2)
44da2e3ebdSchin {
45da2e3ebdSchin 	return (*state.comparf)(*pf1, *pf2);
46da2e3ebdSchin }
47da2e3ebdSchin 
48da2e3ebdSchin /*
49da2e3ebdSchin  * the real thing -- well it used to be
50da2e3ebdSchin  */
51da2e3ebdSchin 
52da2e3ebdSchin int
ftwalk(const char * path,int (* userf)(Ftw_t *),int flags,int (* comparf)(Ftw_t *,Ftw_t *))53da2e3ebdSchin ftwalk(const char* path, int (*userf)(Ftw_t*), int flags, int (*comparf)(Ftw_t*, Ftw_t*))
54da2e3ebdSchin {
55da2e3ebdSchin 	register FTS*		f;
56da2e3ebdSchin 	register FTSENT*	e;
57da2e3ebdSchin 	register int		children;
58da2e3ebdSchin 	register int		rv;
59da2e3ebdSchin 	int			oi;
60da2e3ebdSchin 	int			ns;
61da2e3ebdSchin 	int			os;
62da2e3ebdSchin 	int			nd;
63da2e3ebdSchin 	FTSENT*			x;
64da2e3ebdSchin 	FTSENT*			dd[2];
65da2e3ebdSchin 
66da2e3ebdSchin 	flags ^= FTS_ONEPATH;
67da2e3ebdSchin 	if (flags & FTW_TWICE)
68da2e3ebdSchin 		flags &= ~(FTS_NOPREORDER|FTS_NOPOSTORDER);
69da2e3ebdSchin 	else if (flags & FTW_POST)
70da2e3ebdSchin 		flags |= FTS_NOPREORDER;
71da2e3ebdSchin 	else
72da2e3ebdSchin 		flags |= FTS_NOPOSTORDER;
73da2e3ebdSchin 	if (children = flags & FTW_CHILDREN)
74da2e3ebdSchin 		flags |= FTS_SEEDOT;
75da2e3ebdSchin 	state.comparf = comparf;
76da2e3ebdSchin 	if (!(f = fts_open((char* const*)path, flags, comparf ? ftscompare : 0)))
77da2e3ebdSchin 	{
78da2e3ebdSchin 		if (!path || !(flags & FTS_ONEPATH) && !(path = (const char*)(*((char**)path))))
79da2e3ebdSchin 			return -1;
80da2e3ebdSchin 		ns = strlen(path) + 1;
81da2e3ebdSchin 		if (!(e = newof(0, FTSENT, 1, ns)))
82da2e3ebdSchin 			return -1;
83da2e3ebdSchin 		e->fts_accpath = e->fts_name = e->fts_path = strcpy((char*)(e + 1), path);
84da2e3ebdSchin 		e->fts_namelen = e->fts_pathlen = ns;
85da2e3ebdSchin 		e->fts_info = FTS_NS;
86da2e3ebdSchin 		e->parent = e;
87da2e3ebdSchin 		e->parent->link = e;
88da2e3ebdSchin 		rv = (*userf)((Ftw_t*)e);
89da2e3ebdSchin 		free(e);
90da2e3ebdSchin 		return rv;
91da2e3ebdSchin 	}
92da2e3ebdSchin 	rv = 0;
93da2e3ebdSchin 	if (children && (e = fts_children(f, 0)))
94da2e3ebdSchin 	{
95da2e3ebdSchin 		nd = 0;
96da2e3ebdSchin 		for (x = e; x; x = x->link)
97da2e3ebdSchin 			if (x->info & FTS_DD)
98da2e3ebdSchin 			{
99da2e3ebdSchin 				x->statb = *x->fts_statp;
100da2e3ebdSchin 				x->info &= ~FTS_DD;
101da2e3ebdSchin 				dd[nd++] = x;
102da2e3ebdSchin 				if (nd >= elementsof(dd))
103da2e3ebdSchin 					break;
104da2e3ebdSchin 			}
105da2e3ebdSchin 		e->parent->link = e;
106da2e3ebdSchin 		rv = (*userf)((Ftw_t*)e->parent);
107da2e3ebdSchin 		e->parent->link = 0;
108da2e3ebdSchin 		while (nd > 0)
109da2e3ebdSchin 			dd[--nd]->info |= FTS_DD;
110da2e3ebdSchin 		for (x = e; x; x = x->link)
111da2e3ebdSchin 			if (!(x->info & FTS_D))
112da2e3ebdSchin 				x->status = FTS_SKIP;
113da2e3ebdSchin 	}
114da2e3ebdSchin 	while (!rv && (e = fts_read(f)))
115da2e3ebdSchin 	{
116da2e3ebdSchin 		oi = e->info;
117da2e3ebdSchin 		os = e->status;
118da2e3ebdSchin 		ns = e->status = e->path == e->fts_accpath ? FTW_PATH : FTW_NAME;
119da2e3ebdSchin 		nd = 0;
120da2e3ebdSchin 		switch (e->info)
121da2e3ebdSchin 		{
122da2e3ebdSchin 		case FTS_D:
123da2e3ebdSchin 		case FTS_DNX:
124da2e3ebdSchin 			if (children)
125da2e3ebdSchin 				for (x = fts_children(f, 0); x; x = x->link)
126da2e3ebdSchin 					if (x->info & FTS_DD)
127da2e3ebdSchin 					{
128da2e3ebdSchin 						x->statb = *x->fts_statp;
129da2e3ebdSchin 						x->info &= ~FTS_DD;
130da2e3ebdSchin 						dd[nd++] = x;
131da2e3ebdSchin 						if (nd >= elementsof(dd))
132da2e3ebdSchin 							break;
133da2e3ebdSchin 					}
134da2e3ebdSchin 			break;
135da2e3ebdSchin 		case FTS_DOT:
136da2e3ebdSchin 			continue;
137da2e3ebdSchin 		case FTS_ERR:
138da2e3ebdSchin 			e->info = FTS_NS;
139da2e3ebdSchin 			break;
140da2e3ebdSchin 		case FTS_NSOK:
141da2e3ebdSchin 			e->info = FTS_NSOK;
142da2e3ebdSchin 			break;
143*b30d1939SAndy Fiddaman 		case FTS_SLNONE:
144*b30d1939SAndy Fiddaman 			e->info = FTS_SL;
145*b30d1939SAndy Fiddaman 			break;
146da2e3ebdSchin 		}
147da2e3ebdSchin 		rv = (*userf)((Ftw_t*)e);
148da2e3ebdSchin 		e->info = oi;
149da2e3ebdSchin 		if (e->status == ns)
150da2e3ebdSchin 			e->status = os;
151da2e3ebdSchin 		while (nd > 0)
152da2e3ebdSchin 			dd[--nd]->info |= FTS_DD;
153da2e3ebdSchin 	}
154da2e3ebdSchin 	fts_close(f);
155da2e3ebdSchin 	return rv;
156da2e3ebdSchin }
157