]> git.ipfire.org Git - thirdparty/sarg.git/blobdiff - filelist.c
Add support to decompress xz files
[thirdparty/sarg.git] / filelist.c
index 490259077f5ad435fcdf9906f688f991d56e247d..d4395645d4bdbf6db7564b6b3d6d6b1204a5befc 100644 (file)
@@ -28,6 +28,9 @@
 #include "include/defs.h"
 #include "include/stringbuffer.h"
 #include "include/filelist.h"
+#ifdef HAVE_GLOB_H
+#include <glob.h>
+#endif
 
 struct DirEntryStruct
 {
@@ -85,6 +88,12 @@ struct _FileListIterator
        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
 };
 
 
@@ -417,42 +426,53 @@ static void FileListIter_GetNext(struct _FileListIterator *FIter)
  */
 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++)
+#ifdef HAVE_GLOB_H
+       if (FIter->NextGlob>0)
        {
-               DIter=FIter->DirNodes+Level;
-               DIter->PathLength=Length;;
-               Length+=strlen(DIter->Dir->Name)+1;
-       }
-
-       // get the memory to store the path
-       if (Length>FIter->CurrentPathSize)
-       {
-               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);
 }
 
 /*!
@@ -479,7 +499,7 @@ const char *FileListIter_NextWithMask(struct _FileListIterator *FIter)
        for (Level=FIter->CurrentPathLevel ; Level<=FIter->Level ; Level++)
        {
                DIter=FIter->DirNodes+Level;
-               DIter->PathLength=Length;;
+               DIter->PathLength=Length;
                Length+=strlen(DIter->Dir->Name)+1;
        }
 
@@ -511,6 +531,9 @@ void FileListIter_Close(struct _FileListIterator *FIter)
 {
        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);