ftwalk.c revision 3e14f97f673e8a630f076077de35afdd43dc1587
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner* Copyright (c) 1985-2010 AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* and is licensed under the *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Common Public License, Version 1.0 *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin* by AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* http://www.opensource.org/licenses/cpl1.0.txt *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Glenn Fowler <gsf@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Phong Vo <kpv@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#pragma prototyped
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Glenn Fowler
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * AT&T Research
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * ftwalk on top of fts
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <ast.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <ftwalk.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic struct
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int (*comparf)(Ftw_t*, Ftw_t*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin} state;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * why does fts take FTSENT** instead of FTSENT*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinftscompare(Ftw_t* const* pf1, Ftw_t* const* pf2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (*state.comparf)(*pf1, *pf2);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * the real thing -- well it used to be
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinftwalk(const char* path, int (*userf)(Ftw_t*), int flags, int (*comparf)(Ftw_t*, Ftw_t*))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register FTS* f;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register FTSENT* e;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int children;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int rv;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int oi;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int ns;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int os;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int nd;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin FTSENT* x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin FTSENT* dd[2];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin flags ^= FTS_ONEPATH;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (flags & FTW_TWICE)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin flags &= ~(FTS_NOPREORDER|FTS_NOPOSTORDER);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (flags & FTW_POST)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin flags |= FTS_NOPREORDER;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin flags |= FTS_NOPOSTORDER;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (children = flags & FTW_CHILDREN)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin flags |= FTS_SEEDOT;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state.comparf = comparf;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(f = fts_open((char* const*)path, flags, comparf ? ftscompare : 0)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!path || !(flags & FTS_ONEPATH) && !(path = (const char*)(*((char**)path))))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ns = strlen(path) + 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(e = newof(0, FTSENT, 1, ns)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin e->fts_accpath = e->fts_name = e->fts_path = strcpy((char*)(e + 1), path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin e->fts_namelen = e->fts_pathlen = ns;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin e->fts_info = FTS_NS;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin e->parent = e;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin e->parent->link = e;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rv = (*userf)((Ftw_t*)e);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free(e);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return rv;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rv = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (children && (e = fts_children(f, 0)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin nd = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (x = e; x; x = x->link)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (x->info & FTS_DD)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin x->statb = *x->fts_statp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin x->info &= ~FTS_DD;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin dd[nd++] = x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (nd >= elementsof(dd))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin e->parent->link = e;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rv = (*userf)((Ftw_t*)e->parent);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin e->parent->link = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (nd > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin dd[--nd]->info |= FTS_DD;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (x = e; x; x = x->link)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(x->info & FTS_D))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin x->status = FTS_SKIP;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (!rv && (e = fts_read(f)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin oi = e->info;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin os = e->status;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ns = e->status = e->path == e->fts_accpath ? FTW_PATH : FTW_NAME;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin nd = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (e->info)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case FTS_D:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case FTS_DNX:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (children)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (x = fts_children(f, 0); x; x = x->link)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (x->info & FTS_DD)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin x->statb = *x->fts_statp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin x->info &= ~FTS_DD;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin dd[nd++] = x;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (nd >= elementsof(dd))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case FTS_DOT:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case FTS_ERR:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case FTS_SLNONE:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin e->info = FTS_NS;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case FTS_NSOK:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin e->info = FTS_NSOK;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rv = (*userf)((Ftw_t*)e);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin e->info = oi;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (e->status == ns)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin e->status = os;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (nd > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin dd[--nd]->info |= FTS_DD;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fts_close(f);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return rv;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}