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