xref: /onnv-gate/usr/src/lib/libast/common/misc/ftwalk.c (revision 12068:08a39a083754)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*12068SRoger.Faulkner@Oracle.COM *          Copyright (c) 1985-2010 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
78462SApril.Chin@Sun.COM *                    by AT&T Intellectual Property                     *
84887Schin *                                                                      *
94887Schin *                A copy of the License is available at                 *
104887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
114887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
124887Schin *                                                                      *
134887Schin *              Information and Software Systems Research               *
144887Schin *                            AT&T Research                             *
154887Schin *                           Florham Park NJ                            *
164887Schin *                                                                      *
174887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
184887Schin *                  David Korn <dgk@research.att.com>                   *
194887Schin *                   Phong Vo <kpv@research.att.com>                    *
204887Schin *                                                                      *
214887Schin ***********************************************************************/
224887Schin #pragma prototyped
234887Schin /*
244887Schin  * Glenn Fowler
254887Schin  * AT&T Research
264887Schin  *
274887Schin  * ftwalk on top of fts
284887Schin  */
294887Schin 
304887Schin #include <ast.h>
314887Schin #include <ftwalk.h>
324887Schin 
334887Schin static struct
344887Schin {
354887Schin 	int	(*comparf)(Ftw_t*, Ftw_t*);
364887Schin } state;
374887Schin 
384887Schin /*
394887Schin  * why does fts take FTSENT** instead of FTSENT*
404887Schin  */
414887Schin 
424887Schin static int
ftscompare(Ftw_t * const * pf1,Ftw_t * const * pf2)434887Schin ftscompare(Ftw_t* const* pf1, Ftw_t* const* pf2)
444887Schin {
454887Schin 	return (*state.comparf)(*pf1, *pf2);
464887Schin }
474887Schin 
484887Schin /*
494887Schin  * the real thing -- well it used to be
504887Schin  */
514887Schin 
524887Schin int
ftwalk(const char * path,int (* userf)(Ftw_t *),int flags,int (* comparf)(Ftw_t *,Ftw_t *))534887Schin ftwalk(const char* path, int (*userf)(Ftw_t*), int flags, int (*comparf)(Ftw_t*, Ftw_t*))
544887Schin {
554887Schin 	register FTS*		f;
564887Schin 	register FTSENT*	e;
574887Schin 	register int		children;
584887Schin 	register int		rv;
594887Schin 	int			oi;
604887Schin 	int			ns;
614887Schin 	int			os;
624887Schin 	int			nd;
634887Schin 	FTSENT*			x;
644887Schin 	FTSENT*			dd[2];
654887Schin 
664887Schin 	flags ^= FTS_ONEPATH;
674887Schin 	if (flags & FTW_TWICE)
684887Schin 		flags &= ~(FTS_NOPREORDER|FTS_NOPOSTORDER);
694887Schin 	else if (flags & FTW_POST)
704887Schin 		flags |= FTS_NOPREORDER;
714887Schin 	else
724887Schin 		flags |= FTS_NOPOSTORDER;
734887Schin 	if (children = flags & FTW_CHILDREN)
744887Schin 		flags |= FTS_SEEDOT;
754887Schin 	state.comparf = comparf;
764887Schin 	if (!(f = fts_open((char* const*)path, flags, comparf ? ftscompare : 0)))
774887Schin 	{
784887Schin 		if (!path || !(flags & FTS_ONEPATH) && !(path = (const char*)(*((char**)path))))
794887Schin 			return -1;
804887Schin 		ns = strlen(path) + 1;
814887Schin 		if (!(e = newof(0, FTSENT, 1, ns)))
824887Schin 			return -1;
834887Schin 		e->fts_accpath = e->fts_name = e->fts_path = strcpy((char*)(e + 1), path);
844887Schin 		e->fts_namelen = e->fts_pathlen = ns;
854887Schin 		e->fts_info = FTS_NS;
864887Schin 		e->parent = e;
874887Schin 		e->parent->link = e;
884887Schin 		rv = (*userf)((Ftw_t*)e);
894887Schin 		free(e);
904887Schin 		return rv;
914887Schin 	}
924887Schin 	rv = 0;
934887Schin 	if (children && (e = fts_children(f, 0)))
944887Schin 	{
954887Schin 		nd = 0;
964887Schin 		for (x = e; x; x = x->link)
974887Schin 			if (x->info & FTS_DD)
984887Schin 			{
994887Schin 				x->statb = *x->fts_statp;
1004887Schin 				x->info &= ~FTS_DD;
1014887Schin 				dd[nd++] = x;
1024887Schin 				if (nd >= elementsof(dd))
1034887Schin 					break;
1044887Schin 			}
1054887Schin 		e->parent->link = e;
1064887Schin 		rv = (*userf)((Ftw_t*)e->parent);
1074887Schin 		e->parent->link = 0;
1084887Schin 		while (nd > 0)
1094887Schin 			dd[--nd]->info |= FTS_DD;
1104887Schin 		for (x = e; x; x = x->link)
1114887Schin 			if (!(x->info & FTS_D))
1124887Schin 				x->status = FTS_SKIP;
1134887Schin 	}
1144887Schin 	while (!rv && (e = fts_read(f)))
1154887Schin 	{
1164887Schin 		oi = e->info;
1174887Schin 		os = e->status;
1184887Schin 		ns = e->status = e->path == e->fts_accpath ? FTW_PATH : FTW_NAME;
1194887Schin 		nd = 0;
1204887Schin 		switch (e->info)
1214887Schin 		{
1224887Schin 		case FTS_D:
1234887Schin 		case FTS_DNX:
1244887Schin 			if (children)
1254887Schin 				for (x = fts_children(f, 0); x; x = x->link)
1264887Schin 					if (x->info & FTS_DD)
1274887Schin 					{
1284887Schin 						x->statb = *x->fts_statp;
1294887Schin 						x->info &= ~FTS_DD;
1304887Schin 						dd[nd++] = x;
1314887Schin 						if (nd >= elementsof(dd))
1324887Schin 							break;
1334887Schin 					}
1344887Schin 			break;
1354887Schin 		case FTS_DOT:
1364887Schin 			continue;
1374887Schin 		case FTS_ERR:
1384887Schin 		case FTS_SLNONE:
1394887Schin 			e->info = FTS_NS;
1404887Schin 			break;
1414887Schin 		case FTS_NSOK:
1424887Schin 			e->info = FTS_NSOK;
1434887Schin 			break;
1444887Schin 		}
1454887Schin 		rv = (*userf)((Ftw_t*)e);
1464887Schin 		e->info = oi;
1474887Schin 		if (e->status == ns)
1484887Schin 			e->status = os;
1494887Schin 		while (nd > 0)
1504887Schin 			dd[--nd]->info |= FTS_DD;
1514887Schin 	}
1524887Schin 	fts_close(f);
1534887Schin 	return rv;
1544887Schin }
155