home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
spoc88
/
cengn
/
dirtree.c
< prev
next >
Wrap
Text File
|
1988-06-22
|
7KB
|
169 lines
/************************************************************
DIRTREE.C - by Jake Richter
Provides core routines for traversing a directory tree,
using a "bottom-most first" algorithm.
As presented, code will search the directory tree and
for each directory found, will call a routine called
SearchEngine(), which in turn will process certain files in
that directory in some fashion.
************************************************************/
#include "dos.h" /* Contains ffblk structure. */
#include "dir.h" /* Required by findfirst, findnext,
getcwd. */
/************************************************************
Program Definitions
************************************************************/
#define MAXDIRDEPTH 15 /* Maximum directory depth. */
#define FALSE 0
#define TRUE !FALSE
typedef struct ffblk FFBLK;
/************************************************************
Mandatory Global Declarations
************************************************************/
/* Declare a file info block
for each potential
directory level. */
static FFBLK fileBlock[MAXDIRDEPTH];
static int curDepth = -1; /* Depth indicator. */
static int done; /* Used as a local flag in
the recursive function.
Declared globally to
minimize stack usage
incurred by recursion. */
static char *filename; /* Filename mask for the
Search Engine. */
static char attribute; /* Attribute for engine. */
static void (*funcPtr)(); /* Function ptr for engine*/
/************************************************************
void GetNextDir()
This is the recursive routine that traverses the
directory tree.
************************************************************/
static void GetNextDir()
{
curDepth++; /* Everytime this code gets called, we go down
a level in the tree. */
/* We can't go too deep because we have only
so many file block structures. */
if (curDepth >= MAXDIRDEPTH)
return;
/* Since this section is encountered only when
going down to a new level, (re)initialize
the current level's file block by calling
findfirst. findfirst and findnext return a
TRUE (non-zero) value when all files in the
current directory have been "found". A
separate block is needed for each level
because previously determined information
(set by findfirst and subsequent findnext
calls) must be maintained until an entire
directory level has been searched. */
done = findfirst("*.*", &fileBlock[curDepth], FA_DIREC);
/* It is important to remember that "." and
".." are valid directory names, but that
they also should be ignored while
traversing the tree. The following
conditional in psuedo-code:
while((not all files have been "found")
AND (((the currently found file is really a directory)
AND (this directory starts with "."))
OR (this the file is not really a directory)))
then
get the information of the next file found and check
it against the previous conditions.
*/
while(!done
&& (((fileBlock[curDepth].ff_attrib == FA_DIREC)
&& (fileBlock[curDepth].ff_name[0] == '.'))
|| (fileBlock[curDepth].ff_attrib != FA_DIREC)))
done = findnext(&fileBlock[curDepth]);
/* When we get to this point, one of two
things must be true: either we are out of
files, in which case (done == TRUE), or we
have found the first valid directory name
in the current directory. */
if (!done)
{ /* Since we have found a valid directory, go
to it and repeat the above. */
chdir(fileBlock[curDepth].ff_name);
GetNextDir(); /* Call this routine again. */
chdir(".."); /* Move back up to the correct directory
for this level. */
curDepth--; /* Also adjust the depth gauge. */
}
else
{ /* There are no valid directories below
the current, therefore this one must be at
the end of a branch and should be
processed. */
/* Process this directory. */
SearchEngine(filename, attribute, funcPtr);
return; /* We're done at this level. */
}
/* Get the information about the next file. */
done = findnext(&fileBlock[curDepth]);
/* We are now searching for all other
directories that might be below the current
one. */
while (1)
{ /* This "while" is the same as the previous.*/
while (!done
&& (((fileBlock[curDepth].ff_attrib == FA_DIREC)
&& (fileBlock[curDepth].ff_name[0] == '.'))
|| (fileBlock[curDepth].ff_attrib != FA_DIREC)))
done = findnext(&fileBlock[curDepth]);
if (!done)
{ /* Drop down to the next level. */
chdir(fileBlock[curDepth].ff_name);
GetNextDir(); /* Call this routine again. */
chdir(".."); /* Move back up. */
curDepth--;
/* Prepare for the "while" above. */
done = findnext(&fileBlock[curDepth]);
}
else /* No more files to be found. Break out of
outer loop. */
break;
}
/* Process the current directory since all the
ones below it have already been processed*/
SearchEngine(filename, attribute, funcPtr);
return; /* Bye. */
}
/************************************************************
void DirTree(fname, attr, proc)
This routine sets up the call for the recursive tree
search routine and the search engine.
************************************************************/
void DirTree(fname, attr, proc)
char *fname;
char attr;
void (*proc)();
{
filename = fname; /* Set global variables for Engine.*/
attribute = attr;
funcPtr = proc;
GetNextDir(); /* Initiate recursive search. */
return;
}