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 * |
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; |
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 |
|
|
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; |
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 { |
174 |
} |
} |
175 |
|
|
176 |
return 0; |
return 0; |
177 |
}; |
} |
178 |
|
#endif |
179 |
} |
} |