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