/[svn]/linuxsampler/trunk/src/common/File.cpp
ViewVC logotype

Diff of /linuxsampler/trunk/src/common/File.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1942 by senoner, Sat Jun 6 13:50:36 2009 UTC revision 1943 by persson, Tue Jul 14 18:25:11 2009 UTC
# Line 1  Line 1 
1  /***************************************************************************  /***************************************************************************
2   *                                                                         *   *                                                                         *
3   *   Copyright (C) 2008 Grigor Iliev, Benno Senoner                        *   *   Copyright (C) 2008 - 2009 Grigor Iliev, Benno Senoner                 *
4   *                                                                         *   *                                                                         *
5   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
6   *   it under the terms of the GNU General Public License as published by  *   *   it under the terms of the GNU General Public License as published by  *
# Line 24  Line 24 
24  #include <errno.h>  #include <errno.h>
25  #include <sstream>  #include <sstream>
26  #include <sys/stat.h>  #include <sys/stat.h>
27    #include <dirent.h>
28    
29  #include "Exception.h"  #include "Exception.h"
30  #include "global_private.h"  #include "global_private.h"
31    
32  #if WIN32  #if WIN32
33    #include <windows.h>
 /*  
 dirent.c  
 POSIX WIN32 Directory Browsing parts  
 Copyright (C) 2005 OpenAsthra  
 blogs.openasthra AT gmail.com  
 modifications copyright 2009 by Benno Senoner  
 Licence: LGPL  
 */  
   
 #include "dirent.h"  
 #include <errno.h>  
 #include <io.h>  
 #include <stdlib.h>  
 #include <string.h>  
   
 struct DIR  
 {  
   long handle;  
   long int pos;  
   struct _finddata_t  info;  
   struct dirent d_ent;  
 };  
   
 //aux functions  
 static int StripRegEx(char *name);  
 static int PreOrderTraversal(DIR *dirp, int (*fn) (const char *fpath, const struct stat *sb, int typeflag));  
 static int CallFn(int (*fn) (const char *fpath, const struct stat *sb, int typeflag), char *dirpath, DIR *dirp);  
   
   
 //posix directory browsing API implementation  
   
 DIR *opendir(const char *name)  
 {  
   DIR *dir = NULL;  
   const char *all;  
   long len;  
     
   if((NULL == name) || ('\0' == *name))  
   {  
     errno = EINVAL;  
     return dir;  
   }  
     
   len = strlen(name);  
   all = strchr("/\\", name[len - 1]) ? "*" : "/*";  
       
   len += strlen(all) + 1;  
   
   dir = (DIR *) malloc((len*sizeof(char)) + sizeof(*dir));  
   if(NULL == dir)  
   {  
     errno = ENOMEM;  
     return NULL;  
   }  
       
   dir->d_ent.d_namlen = len;  
   dir->pos = 0;  
   strcpy(dir->d_ent.d_name, name);  
   strcat(dir->d_ent.d_name, all);  
   dir->handle = (long) _findfirst(dir->d_ent.d_name, &dir->info);  
   if(dir->handle == -1)  
   {  
     free(dir);  
     dir = NULL;  
   }  
   
   return dir;  
 }  
   
 int closedir(DIR *dir)  
 {  
   int result = -1;  
   
   if(dir)  
   {  
     if(dir->handle != -1)  
     {  
       result = _findclose(dir->handle);  
     }  
     free(dir);  
   }  
   
   if(result == -1)  
   {  
     errno = EBADF;  
   }  
   
   return result;  
 }  
   
 struct dirent *readdir(DIR *dir)  
 {  
   struct dirent *result = 0;  
   
   if(dir && dir->handle != -1)  
   {  
     if(_findnext(dir->handle, &dir->info) != -1)  
     {  
       result = &dir->d_ent;  
       strcpy(result->d_name, dir->info.name);  
           result->d_type = DT_REG;  
           if(dir->info.attrib & _A_SUBDIR) result->d_type = DT_DIR;  
       dir->pos ++;  
     }  
   }  
   else  
   {  
     errno = EBADF;  
   }  
   
   return result;  
 }  
   
 void rewinddir(DIR *dir)  
 {  
     if(dir && dir->handle != -1)  
     {  
         _findclose(dir->handle);  
         dir->handle = (long) _findfirst(dir->d_ent.d_name, &dir->info);  
         dir->pos = 0;  
     }  
     else  
     {  
         errno = EBADF;  
     }  
 }  
   
 int dirfd(DIR *dirp)  
 {  
   if (NULL == dirp)  
   {  
     return -1;  
   }  
   
   return dirp->handle;  
 }  
   
 void seekdir (DIR *dirp, long int pos)  
 {  
   long int i;  
   
   if (NULL == dirp)  
   {  
     return;  
   }  
   
   if (pos < 0)  
   {  
     pos = dirp->pos + pos;  
     _findclose(dirp->handle);  
     dirp->handle = (long) _findfirst(dirp->d_ent.d_name, &dirp->info);  
   }  
   
   for (i=0; i<pos; i++)  
   {  
     if(_findnext(dirp->handle, &dirp->info) != -1)  
     {  
       dirp->pos ++;  
     }  
     else  
     {  
       break;  
     }  
   }  
   
 }  
   
   
 long int telldir (DIR *dirp)  
 {  
   if (NULL == dirp)  
   {  
     return -1;  
   }  
   
   return dirp->pos;  
   
 }  
   
   
 int scandir(const char *dir, struct dirent ***namelist,  
       int (*filter)(const struct dirent *),  
       int (*compar)(const struct dirent **, const struct dirent **))  
 {  
   struct dirent *result = 0;  
    struct dirent **namlist;  
   int namelistlen = 0;  
   int num_enrties= 0;  
   
   DIR *dirp = opendir(dir);  
   
   if (NULL == dirp)  
   {  
     return -1;  
   }  
   
   if(dirp && dirp->handle != -1)  
   {  
     while(_findnext(dirp->handle, &dirp->info) != -1)  
     {  
       num_enrties++;  
     }  
   }  
   
   rewinddir(dirp);  
   
   namlist = (struct dirent **) malloc(num_enrties * sizeof(struct dirent *));  
   
   if (NULL == namlist)  
   {  
     closedir(dirp);  
     return namelistlen;  
   }  
   
   if(dirp && dirp->handle != -1)  
   {  
     while(_findnext(dirp->handle, &dirp->info) != -1)  
     {  
       result = (struct dirent *) malloc(sizeof(struct dirent) + strlen(dirp->info.name) + 1);  
       strcpy(result->d_name, dirp->info.name);  
           result->d_type = DT_REG;  
           if(dirp->info.attrib & _A_SUBDIR) result->d_type = DT_DIR;  
       if (filter)  
       {  
         if (filter(result))  
         {  
           namlist[namelistlen] = result;  
           namelistlen++;  
         }  
       }  
       else  
       {  
         namlist[namelistlen] = result;  
         namelistlen++;  
       }  
     }  
   }  
   
   //qdirsort(namlist, namelistlen, compar); //todo  
   
   *namelist = namlist;  
   
   closedir(dirp);  
   
   return namelistlen;  
 }  
   
 int ftw(const char *dirpath,  
         int (*fn) (const char *fpath, const struct stat *sb,  
         int typeflag),  
         int nopenfd)  
 {  
   struct dirent *result = 0;  
   struct dirent **namlist;  
   int namelistlen = 0;  
   int num_enrties= 0;  
   struct stat sb;  
   int typeflag = 0;  
   
   DIR *dirp = opendir(dirpath);  
   
   if (NULL == dirp)  
   {  
     return -1;  
   }  
   
   
   if (CallFn(fn, (char *)dirpath, dirp))  
   {  
     closedir(dirp);  
     return 0;  
   }  
   
   if(dirp && (dirp->handle != -1))  
   {  
     while(_findnext(dirp->handle, &dirp->info) != -1)  
     {  
       if ((dirp->info.attrib & _A_SUBDIR) &&  
           (strcmp(dirp->info.name, ".")) && (strcmp(dirp->info.name, "..")))  
       {  
         if (PreOrderTraversal(dirp, fn)>0)  
         {  
           break;  
         }  
       }  
       else  
       {  
         if (CallFn(fn, dirp->info.name, dirp))  
         {  
           break;  
         }  
       }  
     }  
   }  
   
   closedir(dirp);  
   return 0;  
   
 }  
   
 //aux functions  
 int StripRegEx(char *name)  
 {  
   char *t = strstr(name, "/*");  
   if (t)  
   {  
     *t='\0';  
   }  
   else  
   {  
     t = strstr(name, "\\*");  
     if (t)  
     {  
       *t='\0';  
     }  
   }  
   
   return 0;  
 }  
   
 int CallFn(int (*fn) (const char *fpath, const struct stat *sb,  
         int typeflag), char *dirpath, DIR *dirp)  
 {  
   struct stat sb;  
   int typeflag = 0;  
   
   if (fn)  
   {  
     stat(dirpath, &sb);  
     if (dirp->info.attrib & _A_SUBDIR)  
     {  
       typeflag = FTW_D;  
     }  
     else  
     {  
       typeflag = FTW_F;  
     }  
     return fn(dirpath, &sb, typeflag);  
   }  
   return 0;  
 }  
   
   
 int PreOrderTraversal(DIR *dirp, int (*fn) (const char *fpath, const struct stat *sb, int typeflag))  
 {  
   DIR *dirp2;  
   struct stat sb;  
   int typeflag = 0;  
   char *tmpdirnam;  
       
   StripRegEx(dirp->d_ent.d_name);  
   
   tmpdirnam = (char *)malloc(strlen(dirp->d_ent.d_name)+strlen(dirp->info.name)+2);  
   if (!tmpdirnam)  
   {  
     return -1;  
   }  
   
   strcpy(tmpdirnam, dirp->d_ent.d_name);  
   strcat(tmpdirnam, "/");  
   strcat(tmpdirnam, dirp->info.name);  
   
   dirp2 = opendir(tmpdirnam);  
   
   if (NULL == dirp2)  
   {  
     free(tmpdirnam);  
     return -1;  
   }  
   
   if (CallFn(fn, tmpdirnam, dirp2))  
   {  
     free(tmpdirnam);  
     closedir(dirp2);  
     return 1;  
   }  
   
   while(_findnext(dirp2->handle, &dirp2->info) != -1)  
     {  
       if (strcmp(dirp2->info.name, ".."))  
       {  
         if ((dirp2->info.attrib & _A_SUBDIR) && strcmp(dirp2->info.name, ".") && strcmp(dirp2->info.name, ".."))  
         {  
           if (PreOrderTraversal(dirp2, fn))  
           {  
             free(tmpdirnam);  
             closedir(dirp2);  
             return 1;  
           }  
         }  
         else  
         {  
           if (CallFn(fn, dirp2->info.name, dirp2))  
           {  
             free(tmpdirnam);  
             closedir(dirp2);  
             return 1;  
           }  
         }  
       } /*if (strcmp(dirp2->info.name, ".."))*/  
     }  
   
    free(tmpdirnam);  
    closedir(dirp2);  
    return 0;  
     
 }  
   
 /* end of POSIX WIN32 Directory Browsing dirent.c implementation */  
   
   
34  #else  #else
 #include <dirent.h>  
35  #include <ftw.h>  #include <ftw.h>
36  #endif  #endif
37    
38  namespace LinuxSampler {  namespace LinuxSampler {
39    #ifdef WIN32
40        char File::DirSeparator = '\\';
41    #else
42      char File::DirSeparator = '/';      char File::DirSeparator = '/';
43    #endif
44      Mutex File::DirectoryWalkerMutex;      Mutex File::DirectoryWalkerMutex;
45      std::vector<File::DirectoryWalker*> File::DirectoryWalkers;      std::vector<File::DirectoryWalker*> File::DirectoryWalkers;
46      std::string File::DWErrorMsg;      std::string File::DWErrorMsg;
# Line 498  namespace LinuxSampler { Line 89  namespace LinuxSampler {
89                            
90              struct dirent* pEnt = readdir(pDir);              struct dirent* pEnt = readdir(pDir);
91              while (pEnt != NULL) {              while (pEnt != NULL) {
92                  if (pEnt->d_type != DT_REG) {  #ifdef _DIRENT_HAVE_D_TYPE
93                      pEnt = readdir(pDir);              if (pEnt->d_type == DT_REG) {
                     continue;  
                 }  
   
94                  fileList->push_back(std::string(pEnt->d_name));                  fileList->push_back(std::string(pEnt->d_name));
95                }
96    #else
97                struct stat s;
98                if (stat((Dir + DirSeparator + pEnt->d_name).c_str(), &s) == 0 && S_ISREG(s.st_mode)) {
99                    fileList->push_back(std::string(pEnt->d_name));
100                }
101    #endif
102                  pEnt = readdir(pDir);                  pEnt = readdir(pDir);
103              }              }
104                            
# Line 522  namespace LinuxSampler { Line 117  namespace LinuxSampler {
117          File f = File(Dir);          File f = File(Dir);
118          if(!f.Exist()) throw Exception("Fail to stat `" + Dir + "`: " + f.GetErrorMsg());          if(!f.Exist()) throw Exception("Fail to stat `" + Dir + "`: " + f.GetErrorMsg());
119          if(!f.IsDirectory()) throw Exception("The specified path is not a directory: " + Dir);          if(!f.IsDirectory()) throw Exception("The specified path is not a directory: " + Dir);
120            #ifdef WIN32
121            WalkDirectoryTreeSub(Dir, pWalker);
122    #else
123          DirectoryWalkerMutex.Lock();          DirectoryWalkerMutex.Lock();
124          DirectoryWalkers.push_back(pWalker);          DirectoryWalkers.push_back(pWalker);
125          DWErrorMsg = "Failed to process directory tree: " + Dir;          DWErrorMsg = "Failed to process directory tree: " + Dir;
# Line 534  namespace LinuxSampler { Line 131  namespace LinuxSampler {
131              }              }
132          DirectoryWalkers.pop_back();          DirectoryWalkers.pop_back();
133          if (DirectoryWalkers.size() == 0) DirectoryWalkerMutex.Unlock();          if (DirectoryWalkers.size() == 0) DirectoryWalkerMutex.Unlock();
134    #endif
135      }      }
136    
137    #ifdef WIN32
138        void File::WalkDirectoryTreeSub(String Dir, DirectoryWalker* pWalker) {
139            dmsg(2,("File: WalkDirectoryTreeSub(Dir=%s)\n", Dir.c_str()));
140            DWORD attrs = GetFileAttributes(Dir.c_str());
141            if (attrs == INVALID_FILE_ATTRIBUTES) return;
142    
143            if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
144                pWalker->DirectoryEntry(Dir);
145    
146                std::string::size_type l = Dir.length() - 1;
147                if (Dir[l] == '/') Dir[l] = '\\';
148                else if (Dir[l] != '\\') Dir += '\\';
149    
150                WIN32_FIND_DATA fd;
151                HANDLE h = FindFirstFile((Dir + "*").c_str(), &fd);
152                if (h == INVALID_HANDLE_VALUE) return;
153                do {
154                    if (strcmp(fd.cFileName, ".") != 0 &&
155                        strcmp(fd.cFileName, "..") != 0) {
156                        WalkDirectoryTreeSub(Dir + fd.cFileName, pWalker);
157                    }
158                } while (FindNextFile(h, &fd));
159                FindClose(h);
160            } else {
161                pWalker->FileEntry(Dir);
162            }
163        }
164    #else
165      int File::FtwCallback(const char* fpath, const struct stat* sb, int typeflag) {      int File::FtwCallback(const char* fpath, const struct stat* sb, int typeflag) {
166          dmsg(2,("File: FtwCallback(fpath=%s)\n", fpath));          dmsg(2,("File: FtwCallback(fpath=%s)\n", fpath));
167          try {          try {
# Line 549  namespace LinuxSampler { Line 174  namespace LinuxSampler {
174          }          }
175                    
176          return 0;          return 0;
177      };      }
178    #endif
179  }  }

Legend:
Removed from v.1942  
changed lines
  Added in v.1943

  ViewVC Help
Powered by ViewVC