--- linuxsampler/trunk/src/common/File.cpp 2009/07/14 18:20:41 1942 +++ linuxsampler/trunk/src/common/File.cpp 2009/07/14 18:25:11 1943 @@ -1,6 +1,6 @@ /*************************************************************************** * * - * Copyright (C) 2008 Grigor Iliev, Benno Senoner * + * Copyright (C) 2008 - 2009 Grigor Iliev, Benno Senoner * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -24,432 +24,23 @@ #include #include #include +#include #include "Exception.h" #include "global_private.h" #if WIN32 - -/* -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 -#include -#include -#include - -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; ihandle, &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 */ - - +#include #else -#include #include #endif namespace LinuxSampler { - +#ifdef WIN32 + char File::DirSeparator = '\\'; +#else char File::DirSeparator = '/'; - +#endif Mutex File::DirectoryWalkerMutex; std::vector File::DirectoryWalkers; std::string File::DWErrorMsg; @@ -498,12 +89,16 @@ struct dirent* pEnt = readdir(pDir); while (pEnt != NULL) { - if (pEnt->d_type != DT_REG) { - pEnt = readdir(pDir); - continue; - } - +#ifdef _DIRENT_HAVE_D_TYPE + if (pEnt->d_type == DT_REG) { fileList->push_back(std::string(pEnt->d_name)); + } +#else + struct stat s; + if (stat((Dir + DirSeparator + pEnt->d_name).c_str(), &s) == 0 && S_ISREG(s.st_mode)) { + fileList->push_back(std::string(pEnt->d_name)); + } +#endif pEnt = readdir(pDir); } @@ -522,7 +117,9 @@ File f = File(Dir); if(!f.Exist()) throw Exception("Fail to stat `" + Dir + "`: " + f.GetErrorMsg()); if(!f.IsDirectory()) throw Exception("The specified path is not a directory: " + Dir); - +#ifdef WIN32 + WalkDirectoryTreeSub(Dir, pWalker); +#else DirectoryWalkerMutex.Lock(); DirectoryWalkers.push_back(pWalker); DWErrorMsg = "Failed to process directory tree: " + Dir; @@ -534,9 +131,37 @@ } DirectoryWalkers.pop_back(); if (DirectoryWalkers.size() == 0) DirectoryWalkerMutex.Unlock(); +#endif } - +#ifdef WIN32 + void File::WalkDirectoryTreeSub(String Dir, DirectoryWalker* pWalker) { + dmsg(2,("File: WalkDirectoryTreeSub(Dir=%s)\n", Dir.c_str())); + DWORD attrs = GetFileAttributes(Dir.c_str()); + if (attrs == INVALID_FILE_ATTRIBUTES) return; + + if (attrs & FILE_ATTRIBUTE_DIRECTORY) { + pWalker->DirectoryEntry(Dir); + + std::string::size_type l = Dir.length() - 1; + if (Dir[l] == '/') Dir[l] = '\\'; + else if (Dir[l] != '\\') Dir += '\\'; + + WIN32_FIND_DATA fd; + HANDLE h = FindFirstFile((Dir + "*").c_str(), &fd); + if (h == INVALID_HANDLE_VALUE) return; + do { + if (strcmp(fd.cFileName, ".") != 0 && + strcmp(fd.cFileName, "..") != 0) { + WalkDirectoryTreeSub(Dir + fd.cFileName, pWalker); + } + } while (FindNextFile(h, &fd)); + FindClose(h); + } else { + pWalker->FileEntry(Dir); + } + } +#else int File::FtwCallback(const char* fpath, const struct stat* sb, int typeflag) { dmsg(2,("File: FtwCallback(fpath=%s)\n", fpath)); try { @@ -549,5 +174,6 @@ } return 0; - }; + } +#endif }