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