Recursive directory scan. Method: Scan a directory for files.

Return TypeFunction nameArguments
hzEcode_scanfiles_r(hzArray<hzString>&,hzArray<hzString>&,hzString&,uint32_t,bool,)

Declared and defined in file: hzDirectory.cpp

Function Logic:

0:START 1:unknown 2:Return E_ARGUMENT 3:unknown 4:unknown 5:Return E_ARGUMENT 6:part 7:unknown 8:pDir 9:unknown 10:Return E_OPENFAIL 11:unknown 12:unknown 13:unknown 14:unknown 15:teststr 16:pathsofar 17:teststr 18:teststr 19:unknown 20:items items 21:Return E_CORRUPT 22:unknown 23:items 24:items 25:Return E_OK 26:pDir 27:unknown 28:Return E_OPENFAIL 29:unknown 30:unknown 31:unknown 32:unknown 33:teststr 34:pathsofar 35:teststr 36:teststr 37:unknown 38:items items 39:Return E_CORRUPT 40:unknown 41:items 42:unknown 43:part 44:part 45:pDir 46:unknown 47:Return E_OPENFAIL 48:unknown 49:unknown 50:unknown 51:unknown 52:teststr 53:pathsofar 54:teststr 55:teststr 56:unknown 57:items items 58:Return E_CORRUPT 59:unknown 60:items 61:unknown 62:unknown 63:items 64:items 65:Return E_OK

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 ;
}