|
version 1.6, 2009/06/06 13:50:36
|
version 1.7, 2009/07/14 18:25:11
|
|
|
|
| /*************************************************************************** | /*************************************************************************** |
| * * | * * |
| * 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 * | * 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 * | * it under the terms of the GNU General Public License as published by * |
|
|
|
| #include <errno.h> | #include <errno.h> |
| #include <sstream> | #include <sstream> |
| #include <sys/stat.h> | #include <sys/stat.h> |
| |
#include <dirent.h> |
| | |
| #include "Exception.h" | #include "Exception.h" |
| #include "global_private.h" | #include "global_private.h" |
| | |
| #if WIN32 | #if WIN32 |
| |
#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 */ |
|
| |
|
| |
|
| #else | #else |
| #include <dirent.h> |
|
| #include <ftw.h> | #include <ftw.h> |
| #endif | #endif |
| | |
| namespace LinuxSampler { | namespace LinuxSampler { |
| |
#ifdef WIN32 |
| |
char File::DirSeparator = '\\'; |
| |
#else |
| char File::DirSeparator = '/'; | char File::DirSeparator = '/'; |
| |
#endif |
| Mutex File::DirectoryWalkerMutex; | Mutex File::DirectoryWalkerMutex; |
| std::vector<File::DirectoryWalker*> File::DirectoryWalkers; | std::vector<File::DirectoryWalker*> File::DirectoryWalkers; |
| std::string File::DWErrorMsg; | std::string File::DWErrorMsg; |
|
|
|
| | |
| struct dirent* pEnt = readdir(pDir); | struct dirent* pEnt = readdir(pDir); |
| while (pEnt != NULL) { | while (pEnt != NULL) { |
| if (pEnt->d_type != DT_REG) { |
#ifdef _DIRENT_HAVE_D_TYPE |
| pEnt = readdir(pDir); |
if (pEnt->d_type == DT_REG) { |
| continue; |
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)); | fileList->push_back(std::string(pEnt->d_name)); |
| |
} |
| |
#endif |
| pEnt = readdir(pDir); | pEnt = readdir(pDir); |
| } | } |
| | |
|
|
|
| File f = File(Dir); | File f = File(Dir); |
| if(!f.Exist()) throw Exception("Fail to stat `" + Dir + "`: " + f.GetErrorMsg()); | if(!f.Exist()) throw Exception("Fail to stat `" + Dir + "`: " + f.GetErrorMsg()); |
| 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); |
| |
#ifdef WIN32 |
| |
WalkDirectoryTreeSub(Dir, pWalker); |
| |
#else |
| DirectoryWalkerMutex.Lock(); | DirectoryWalkerMutex.Lock(); |
| DirectoryWalkers.push_back(pWalker); | DirectoryWalkers.push_back(pWalker); |
| DWErrorMsg = "Failed to process directory tree: " + Dir; | DWErrorMsg = "Failed to process directory tree: " + Dir; |
|
|
|
| } | } |
| DirectoryWalkers.pop_back(); | DirectoryWalkers.pop_back(); |
| if (DirectoryWalkers.size() == 0) DirectoryWalkerMutex.Unlock(); | 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) { | int File::FtwCallback(const char* fpath, const struct stat* sb, int typeflag) { |
| dmsg(2,("File: FtwCallback(fpath=%s)\n", fpath)); | dmsg(2,("File: FtwCallback(fpath=%s)\n", fpath)); |
| try { | try { |
|
|
|
| } | } |
| | |
| return 0; | return 0; |
| }; |
} |
| |
#endif |
| } | } |