14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*8462SApril.Chin@Sun.COM * Copyright (c) 1985-2008 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 7*8462SApril.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 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 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