1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin * *
3da2e3ebdSchin * This software is part of the ast package *
4*3e14f97fSRoger A. Faulkner * Copyright (c) 1985-2010 AT&T Intellectual Property *
5da2e3ebdSchin * and is licensed under the *
6da2e3ebdSchin * Common Public License, Version 1.0 *
77c2fbfb3SApril Chin * by AT&T Intellectual Property *
8da2e3ebdSchin * *
9da2e3ebdSchin * A copy of the License is available at *
10da2e3ebdSchin * http://www.opensource.org/licenses/cpl1.0.txt *
11da2e3ebdSchin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
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 case FTS_SLNONE:
139da2e3ebdSchin e->info = FTS_NS;
140da2e3ebdSchin break;
141da2e3ebdSchin case FTS_NSOK:
142da2e3ebdSchin e->info = FTS_NSOK;
143da2e3ebdSchin break;
144da2e3ebdSchin }
145da2e3ebdSchin rv = (*userf)((Ftw_t*)e);
146da2e3ebdSchin e->info = oi;
147da2e3ebdSchin if (e->status == ns)
148da2e3ebdSchin e->status = os;
149da2e3ebdSchin while (nd > 0)
150da2e3ebdSchin dd[--nd]->info |= FTS_DD;
151da2e3ebdSchin }
152da2e3ebdSchin fts_close(f);
153da2e3ebdSchin return rv;
154da2e3ebdSchin }
155