Recursive directory scan. Method: Scan a directory for files.
| Return Type | Function name | Arguments |
|---|---|---|
| hzEcode | _scanfiles_r | (hzArray<hzString>&,hzArray<hzString>&,hzString&,uint32_t,bool,) |
Declared and defined in file: hzDirectory.cpp
Function Logic:
Function body:
hzEcode _scanfiles_r (hzArray<hzString>& files)hzArray<hzString>& parts, hzString& pathsofar, uint32_t nLevel, bool bLimit,
{
// Category: Directory
//
// Recursive directory scan.
//
// Method: Scan a directory for files.
//
// Arguments: 1) files Repository for files found. This is only populated here if we are on the last part of the criteria given in the 2nd argument
// 2) parts The parts of the path (eg /home/username has parts of home and username)
// 3) Pathsofar the directory to be read in this invokation.
// 4) Level this determines if we are in the last part of the directory to be scanned.
// 5) Limit If set we do not go into sub-directories of the directory to be scanned for files.
//
// Returns: E_ARGUMENT If the pathsofar is empty or no parts are specified
// E_OPENFAIL If the directory cannot be opened
// E_CORRUPT If a directory entry cannot be stated
// E_OK If the directory is successfully scanned
_hzfunc("_scanfiles_r") ;
hzVect<hzString> levels ; // Partial paths
hzVect<hzString> dirs ; // Needed only for ListDir function
FSTAT fs ; // Directory entry status
dirent* pDE ; // Directory entry
DIR* pDir ; // Directory pointer
hzString teststr ; // File/dir to be tested with stat
hzString part ; // This part (of the criteria)
// Check arguments
if (!pathsofar || !parts.Count())
return E_ARGUMENT ;
if (bLimit)
{
// Search for files is limited to specified directories. The last part of the criteria will be matched only on files
if (nLevel < 0|| nLevel >&eq; parts.Count())
return E_ARGUMENT ;
part = parts[nLevel] ;
// Are we on the last part of the path in which the filename criteria is specified?
if (nLevel == (parts.Count() - 1))
{
// We are so we are just looking for file that match. No directories are taken into account
pDir = opendir(*pathsofar) ;
if (!pDir)
return E_OPENFAIL ;
for (; pDE = readdir(pDir) ;)
{
if (pDE->d_name[0]== ''.''&&(pDE->d_name[1]== 0|| (pDE->d_name[1]== ''.''&&pDE->d_name[2]== 0)))
continue ;
if (!FormCheckCstr(pDE->d_name, *part))
continue ;
// Build the complete path to the file before calling stat. This is nessesary since we are not actually in the directory
// as we have never called chdir()
// Test for path of /
if (pathsofar.Length() == 1)
teststr = "/" ;
else
teststr = pathsofar + "/" ;
teststr += pDE->d_name ;
if (stat(*teststr, &fs) == -1)
{
closedir(pDir) ;
hzerr(E_CORRUPT, "Could not stat directory entry %s", *teststr) ;
return E_CORRUPT ;
}
// Only add the entry if it is a file
if (S_ISREG(fs.st_mode))
files.Add(teststr) ;
}
closedir(pDir) ;
return E_OK ;
}
// We are not on the last part so olny look for directories matching the current part criteria. Then for each directory call the
// next level.
pDir = opendir(*pathsofar) ;
if (!pDir)
return E_OPENFAIL ;
for (; pDE = readdir(pDir) ;)
{
if (pDE->d_name[0]== ''.''&&(pDE->d_name[1]== 0|| (pDE->d_name[1]== ''.''&&pDE->d_name[2]== 0)))
continue ;
if (!FormCheckCstr(pDE->d_name, *part))
continue ;
if (pathsofar.Length() == 1)
teststr = "/" ;
else
teststr = pathsofar + "/" ;
teststr += pDE->d_name ;
if (stat(*teststr, &fs) == -1)
{
closedir(pDir) ;
hzerr(E_CORRUPT, "Could not stat directory entry %s", *teststr) ;
return E_CORRUPT ;
}
// Only call next level if the entry is a directory
if (S_ISDIR(fs.st_mode))
_scanfiles_r(files, parts, teststr, nLevel + 1,bLimit) ;
}
}
else
{
// Search for files is not limited to specified directories. The last part of the criteria will be matched on both on files
// and directories. Where files match this last part they are included as they are in the limited search. Where directories
// match this last part all thier files and all the files of all thier subdirectories are included. The purpose of this
// mode of operation is to facilitate a tar-like interpretation of a directory. Eg the criteria dvlp/* means the directory
// of dvlp (in the current dir) and every file in it and below it.
// On top level?
if (nLevel > (parts.Count() - 1))
part = parts[parts.Count() - 1];
else
part = parts[nLevel] ;
// We are not on the last part so olny look for directories matching the current part criteria. Then for each directory call the
// next level.
pDir = opendir(*pathsofar) ;
if (!pDir)
return E_OPENFAIL ;
for (; pDE = readdir(pDir) ;)
{
if (pDE->d_name[0]== ''.''&&(pDE->d_name[1]== 0|| (pDE->d_name[1]== ''.''&&pDE->d_name[2]== 0)))
continue ;
if (!FormCheckCstr(pDE->d_name, *part))
continue ;
if (pathsofar.Length() == 1)
teststr = "/" ;
else
teststr = pathsofar + "/" ;
teststr += pDE->d_name ;
if (stat(*teststr, &fs) == -1)
{
closedir(pDir) ;
hzerr(E_CORRUPT, "Could not stat directory entry %s", *teststr) ;
return E_CORRUPT ;
}
// Current part is a dir?
if (S_ISDIR(fs.st_mode))
_scanfiles_r(files, parts, teststr, nLevel + 1,bLimit) ;
// Current part is a file
if (S_ISREG(fs.st_mode))
{
// If on last part or above add the files
if (nLevel >&eq; (parts.Count() - 1))
files.Add(teststr) ;
}
}
}
closedir(pDir) ;
return E_OK ;
}