/*
* SARG Squid Analysis Report Generator http://sarg.sourceforge.net
- * 1998, 2013
+ * 1998, 2015
*
* SARG donations:
* please look at http://sarg.sourceforge.net/donations.php
#include "include/defs.h"
#include "include/stringbuffer.h"
#include "include/filelist.h"
+#ifdef HAVE_GLOB_H
+#include <glob.h>
+#endif
struct DirEntryStruct
{
int Level;
//! The current node at each level.
struct DirEntryIterator *DirNodes;
+#ifdef HAVE_GLOB_H
+ //! Next globbed file to return
+ int NextGlob;
+ //! Buffer with the globbed files.
+ glob_t Glob;
+#endif
};
return(FileList_AddFileRecursive(FObj,&FObj->First,FileName));
}
+/*!
+ * \brief Is the file list empty?
+ *
+ * \param FObj The file list to check.
+ *
+ * \return \c True if the file list is empty or \c false if
+ * there is at least one file in the list.
+ */
+bool FileList_IsEmpty(FileListObject FObj)
+{
+ if (!FObj) return(true);
+ if (FObj->First==NULL) return(true);
+ return(false);
+}
+
/*!
* Recursively measure the tree depth.
*
struct _FileListIterator *FIter;
struct DirEntryStruct *Dir;
+ if (!FObj) return(NULL);
FIter=(FileListIterator)calloc(1,sizeof(*FIter));
if (!FIter) return(NULL);
FIter->Parent=FObj;
{
if (FIter->Level>=FIter->TreeDepth) break;
Dir=Dir->Child;
- FIter->DirNodes[FIter->Level++].Dir=Dir;
+ FIter->DirNodes[++FIter->Level].Dir=Dir;
}
break;
}
*/
const char *FileListIter_Next(struct _FileListIterator *FIter)
{
- int Length;
- int Level;
- struct DirEntryIterator *DIter;
+ const char *Path;
- if (!FIter) return(NULL);
- if (!FIter->DirNodes) return(NULL);
- if (FIter->Level<0 || FIter->Level>=FIter->TreeDepth) return(NULL);
-
- // how much space to store the path
- Length=FIter->DirNodes[FIter->CurrentPathLevel].PathLength;
- for (Level=FIter->CurrentPathLevel ; Level<=FIter->Level ; Level++)
- {
- DIter=FIter->DirNodes+Level;
- DIter->PathLength=Length;;
- Length+=strlen(DIter->Dir->Name)+1;
- }
-
- // get the memory to store the path
- if (Length>FIter->CurrentPathSize)
+#ifdef HAVE_GLOB_H
+ if (FIter->NextGlob>0)
{
- char *temp=realloc(FIter->CurrentPath,Length);
- if (!temp) return(NULL);
- FIter->CurrentPath=temp;
- FIter->CurrentPathSize=Length;
+ if (FIter->NextGlob<FIter->Glob.gl_pathc)
+ {
+ Path=FIter->Glob.gl_pathv[FIter->NextGlob++];
+ return(Path);
+ }
+ globfree(&FIter->Glob);
+ FIter->NextGlob=0;
}
-
- for (Level=FIter->CurrentPathLevel ; Level<=FIter->Level ; Level++)
+ Path=FileListIter_NextWithMask(FIter);
+ if (Path!=NULL && (Path[0]!='-' || Path[1]!='\0'))
{
- DIter=FIter->DirNodes+Level;
- if (Level>0) FIter->CurrentPath[DIter->PathLength-1]='/';
- strcpy(FIter->CurrentPath+DIter->PathLength,DIter->Dir->Name);
+ int ErrCode=glob(Path,GLOB_ERR | GLOB_NOSORT,NULL,&FIter->Glob);
+ if (ErrCode!=0)
+ {
+ switch (ErrCode)
+ {
+ case GLOB_NOSPACE:
+ debuga(__FILE__,__LINE__,_("Not enough memory to read the files matching \"%s\"\n"),Path);
+ break;
+ case GLOB_ABORTED:
+ debuga(__FILE__,__LINE__,_("Read error while listing the files matching \"%s\"\n"),Path);
+ break;
+ case GLOB_NOMATCH:
+ debuga(__FILE__,__LINE__,_("No files matching \"%s\"\n"),Path);
+ break;
+ default:
+ debuga(__FILE__,__LINE__,_("Failed to glob file pattern \"%s\" with unspecified error code %d"),Path,ErrCode);
+ break;
+ }
+ exit(EXIT_FAILURE);
+ }
+ Path=FIter->Glob.gl_pathv[0];
+ FIter->NextGlob=1;
}
- FIter->CurrentPathLevel=Level;
-
- FileListIter_GetNext(FIter);
- return(FIter->CurrentPath);
+#else
+ /*
+ * Fall back to a simple enumeration. In that case, the user cannot use
+ * wildcards as they won't be expended.
+ */
+ Path=FileListIter_NextWithMask(FIter);
+#endif
+ return(Path);
}
/*!
for (Level=FIter->CurrentPathLevel ; Level<=FIter->Level ; Level++)
{
DIter=FIter->DirNodes+Level;
- DIter->PathLength=Length;;
+ DIter->PathLength=Length;
Length+=strlen(DIter->Dir->Name)+1;
}
{
if (FIter)
{
+#ifdef HAVE_GLOB_H
+ if (FIter->NextGlob>0) globfree(&FIter->Glob);
+#endif
if (FIter->CurrentPath) free(FIter->CurrentPath);
if (FIter->DirNodes) free(FIter->DirNodes);
free(FIter);