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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1911 - (hide annotations) (download)
Sat Jun 6 13:50:36 2009 UTC (14 years, 10 months ago) by senoner
File size: 12083 byte(s)
* InstrumentsDB on Windows now works in both standalone and VST mode
* DB is stored in %USERPROFILE%\.linuxsampler\instruments.db
* removed stat() implementation as mingw already provides it

1 iliev 1717 /***************************************************************************
2     * *
3     * Copyright (C) 2008 Grigor Iliev, Benno Senoner *
4     * *
5     * 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 *
7     * the Free Software Foundation; either version 2 of the License, or *
8     * (at your option) any later version. *
9     * *
10     * This program is distributed in the hope that it will be useful, *
11     * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13     * GNU General Public License for more details. *
14     * *
15     * You should have received a copy of the GNU General Public License *
16     * along with this program; if not, write to the Free Software *
17     * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, *
18     * MA 02110-1301 USA *
19     ***************************************************************************/
20    
21     #include "File.h"
22    
23 persson 1726 #include <cstring>
24 iliev 1717 #include <errno.h>
25     #include <sstream>
26 senoner 1911 #include <sys/stat.h>
27 iliev 1717
28     #include "Exception.h"
29     #include "global_private.h"
30    
31     #if WIN32
32    
33 senoner 1910 /*
34     dirent.c
35     POSIX WIN32 Directory Browsing parts
36     Copyright (C) 2005 OpenAsthra
37     blogs.openasthra AT gmail.com
38     modifications copyright 2009 by Benno Senoner
39     Licence: LGPL
40     */
41    
42     #include "dirent.h"
43     #include <errno.h>
44     #include <io.h>
45     #include <stdlib.h>
46     #include <string.h>
47    
48     struct DIR
49     {
50     long handle;
51     long int pos;
52     struct _finddata_t info;
53     struct dirent d_ent;
54     };
55    
56     //aux functions
57     static int StripRegEx(char *name);
58     static int PreOrderTraversal(DIR *dirp, int (*fn) (const char *fpath, const struct stat *sb, int typeflag));
59     static int CallFn(int (*fn) (const char *fpath, const struct stat *sb, int typeflag), char *dirpath, DIR *dirp);
60    
61    
62     //posix directory browsing API implementation
63    
64     DIR *opendir(const char *name)
65     {
66     DIR *dir = NULL;
67     const char *all;
68     long len;
69    
70     if((NULL == name) || ('\0' == *name))
71     {
72     errno = EINVAL;
73     return dir;
74     }
75    
76     len = strlen(name);
77     all = strchr("/\\", name[len - 1]) ? "*" : "/*";
78    
79     len += strlen(all) + 1;
80    
81     dir = (DIR *) malloc((len*sizeof(char)) + sizeof(*dir));
82     if(NULL == dir)
83     {
84     errno = ENOMEM;
85     return NULL;
86     }
87    
88     dir->d_ent.d_namlen = len;
89     dir->pos = 0;
90     strcpy(dir->d_ent.d_name, name);
91     strcat(dir->d_ent.d_name, all);
92     dir->handle = (long) _findfirst(dir->d_ent.d_name, &dir->info);
93     if(dir->handle == -1)
94     {
95     free(dir);
96     dir = NULL;
97     }
98    
99     return dir;
100     }
101    
102     int closedir(DIR *dir)
103     {
104     int result = -1;
105    
106     if(dir)
107     {
108     if(dir->handle != -1)
109     {
110     result = _findclose(dir->handle);
111     }
112     free(dir);
113     }
114    
115     if(result == -1)
116     {
117     errno = EBADF;
118     }
119    
120     return result;
121     }
122    
123     struct dirent *readdir(DIR *dir)
124     {
125     struct dirent *result = 0;
126    
127     if(dir && dir->handle != -1)
128     {
129     if(_findnext(dir->handle, &dir->info) != -1)
130     {
131     result = &dir->d_ent;
132     strcpy(result->d_name, dir->info.name);
133     result->d_type = DT_REG;
134     if(dir->info.attrib & _A_SUBDIR) result->d_type = DT_DIR;
135     dir->pos ++;
136     }
137     }
138     else
139     {
140     errno = EBADF;
141     }
142    
143     return result;
144     }
145    
146     void rewinddir(DIR *dir)
147     {
148     if(dir && dir->handle != -1)
149     {
150     _findclose(dir->handle);
151     dir->handle = (long) _findfirst(dir->d_ent.d_name, &dir->info);
152     dir->pos = 0;
153     }
154     else
155     {
156     errno = EBADF;
157     }
158     }
159    
160     int dirfd(DIR *dirp)
161     {
162     if (NULL == dirp)
163     {
164     return -1;
165     }
166    
167     return dirp->handle;
168     }
169    
170     void seekdir (DIR *dirp, long int pos)
171     {
172     long int i;
173    
174     if (NULL == dirp)
175     {
176     return;
177     }
178    
179     if (pos < 0)
180     {
181     pos = dirp->pos + pos;
182     _findclose(dirp->handle);
183     dirp->handle = (long) _findfirst(dirp->d_ent.d_name, &dirp->info);
184     }
185    
186     for (i=0; i<pos; i++)
187     {
188     if(_findnext(dirp->handle, &dirp->info) != -1)
189     {
190     dirp->pos ++;
191     }
192     else
193     {
194     break;
195     }
196     }
197    
198     }
199    
200    
201     long int telldir (DIR *dirp)
202     {
203     if (NULL == dirp)
204     {
205     return -1;
206     }
207    
208     return dirp->pos;
209    
210     }
211    
212    
213     int scandir(const char *dir, struct dirent ***namelist,
214     int (*filter)(const struct dirent *),
215     int (*compar)(const struct dirent **, const struct dirent **))
216     {
217     struct dirent *result = 0;
218     struct dirent **namlist;
219     int namelistlen = 0;
220     int num_enrties= 0;
221    
222     DIR *dirp = opendir(dir);
223    
224     if (NULL == dirp)
225     {
226     return -1;
227     }
228    
229     if(dirp && dirp->handle != -1)
230     {
231     while(_findnext(dirp->handle, &dirp->info) != -1)
232     {
233     num_enrties++;
234     }
235     }
236    
237     rewinddir(dirp);
238    
239     namlist = (struct dirent **) malloc(num_enrties * sizeof(struct dirent *));
240    
241     if (NULL == namlist)
242     {
243     closedir(dirp);
244     return namelistlen;
245     }
246    
247     if(dirp && dirp->handle != -1)
248     {
249     while(_findnext(dirp->handle, &dirp->info) != -1)
250     {
251     result = (struct dirent *) malloc(sizeof(struct dirent) + strlen(dirp->info.name) + 1);
252     strcpy(result->d_name, dirp->info.name);
253     result->d_type = DT_REG;
254     if(dirp->info.attrib & _A_SUBDIR) result->d_type = DT_DIR;
255     if (filter)
256     {
257     if (filter(result))
258     {
259     namlist[namelistlen] = result;
260     namelistlen++;
261     }
262     }
263     else
264     {
265     namlist[namelistlen] = result;
266     namelistlen++;
267     }
268     }
269     }
270    
271     //qdirsort(namlist, namelistlen, compar); //todo
272    
273     *namelist = namlist;
274    
275     closedir(dirp);
276    
277     return namelistlen;
278     }
279    
280     int ftw(const char *dirpath,
281     int (*fn) (const char *fpath, const struct stat *sb,
282     int typeflag),
283     int nopenfd)
284     {
285     struct dirent *result = 0;
286     struct dirent **namlist;
287     int namelistlen = 0;
288     int num_enrties= 0;
289     struct stat sb;
290     int typeflag = 0;
291    
292     DIR *dirp = opendir(dirpath);
293    
294     if (NULL == dirp)
295     {
296     return -1;
297     }
298    
299    
300     if (CallFn(fn, (char *)dirpath, dirp))
301     {
302     closedir(dirp);
303     return 0;
304     }
305    
306     if(dirp && (dirp->handle != -1))
307     {
308     while(_findnext(dirp->handle, &dirp->info) != -1)
309     {
310     if ((dirp->info.attrib & _A_SUBDIR) &&
311     (strcmp(dirp->info.name, ".")) && (strcmp(dirp->info.name, "..")))
312     {
313     if (PreOrderTraversal(dirp, fn)>0)
314     {
315     break;
316     }
317     }
318     else
319     {
320     if (CallFn(fn, dirp->info.name, dirp))
321     {
322     break;
323     }
324     }
325     }
326     }
327    
328     closedir(dirp);
329     return 0;
330    
331     }
332    
333     //aux functions
334     int StripRegEx(char *name)
335     {
336     char *t = strstr(name, "/*");
337     if (t)
338     {
339     *t='\0';
340     }
341     else
342     {
343     t = strstr(name, "\\*");
344     if (t)
345     {
346     *t='\0';
347     }
348     }
349    
350     return 0;
351     }
352    
353     int CallFn(int (*fn) (const char *fpath, const struct stat *sb,
354     int typeflag), char *dirpath, DIR *dirp)
355     {
356     struct stat sb;
357     int typeflag = 0;
358    
359     if (fn)
360     {
361     stat(dirpath, &sb);
362     if (dirp->info.attrib & _A_SUBDIR)
363     {
364     typeflag = FTW_D;
365     }
366     else
367     {
368     typeflag = FTW_F;
369     }
370     return fn(dirpath, &sb, typeflag);
371     }
372     return 0;
373     }
374    
375    
376     int PreOrderTraversal(DIR *dirp, int (*fn) (const char *fpath, const struct stat *sb, int typeflag))
377     {
378     DIR *dirp2;
379     struct stat sb;
380     int typeflag = 0;
381     char *tmpdirnam;
382    
383     StripRegEx(dirp->d_ent.d_name);
384    
385     tmpdirnam = (char *)malloc(strlen(dirp->d_ent.d_name)+strlen(dirp->info.name)+2);
386     if (!tmpdirnam)
387     {
388     return -1;
389     }
390    
391     strcpy(tmpdirnam, dirp->d_ent.d_name);
392     strcat(tmpdirnam, "/");
393     strcat(tmpdirnam, dirp->info.name);
394    
395     dirp2 = opendir(tmpdirnam);
396    
397     if (NULL == dirp2)
398     {
399     free(tmpdirnam);
400     return -1;
401     }
402    
403     if (CallFn(fn, tmpdirnam, dirp2))
404     {
405     free(tmpdirnam);
406     closedir(dirp2);
407     return 1;
408     }
409    
410     while(_findnext(dirp2->handle, &dirp2->info) != -1)
411     {
412     if (strcmp(dirp2->info.name, ".."))
413     {
414     if ((dirp2->info.attrib & _A_SUBDIR) && strcmp(dirp2->info.name, ".") && strcmp(dirp2->info.name, ".."))
415     {
416     if (PreOrderTraversal(dirp2, fn))
417     {
418     free(tmpdirnam);
419     closedir(dirp2);
420     return 1;
421     }
422     }
423     else
424     {
425     if (CallFn(fn, dirp2->info.name, dirp2))
426     {
427     free(tmpdirnam);
428     closedir(dirp2);
429     return 1;
430     }
431     }
432     } /*if (strcmp(dirp2->info.name, ".."))*/
433     }
434    
435     free(tmpdirnam);
436     closedir(dirp2);
437     return 0;
438    
439     }
440    
441     /* end of POSIX WIN32 Directory Browsing dirent.c implementation */
442    
443    
444 iliev 1717 #else
445     #include <dirent.h>
446     #include <ftw.h>
447     #endif
448    
449     namespace LinuxSampler {
450    
451     char File::DirSeparator = '/';
452    
453 senoner 1910 Mutex File::DirectoryWalkerMutex;
454 iliev 1717 std::vector<File::DirectoryWalker*> File::DirectoryWalkers;
455     std::string File::DWErrorMsg;
456    
457     File::File(std::string Path) {
458     bExist = !stat(Path.c_str(), &Status);
459     if(!bExist) ErrorMsg = strerror(errno);
460     }
461    
462     bool File::Exist() {
463     return bExist;
464     }
465    
466     std::string File::GetErrorMsg() {
467     return ErrorMsg;
468     }
469    
470     bool File::IsFile() {
471     if(!Exist()) return false;
472    
473     return S_ISREG(Status.st_mode);
474     }
475    
476     bool File::IsDirectory() {
477     if(!Exist()) return false;
478    
479     return S_ISDIR(Status.st_mode);
480     }
481    
482     unsigned long File::GetSize() {
483     if(!Exist()) return 0;
484    
485 senoner 1910 return Status.st_size;
486 iliev 1717 }
487    
488     FileListPtr File::GetFiles(std::string Dir) {
489     DIR* pDir = opendir(Dir.c_str());
490     if (pDir == NULL) {
491     std::stringstream ss;
492     ss << "Failed to list the directory content of `";
493     ss << Dir << "`: " << strerror(errno);
494     throw Exception(ss.str());
495     }
496    
497     FileListPtr fileList(new std::vector<std::string>);
498    
499     struct dirent* pEnt = readdir(pDir);
500     while (pEnt != NULL) {
501     if (pEnt->d_type != DT_REG) {
502     pEnt = readdir(pDir);
503     continue;
504     }
505    
506     fileList->push_back(std::string(pEnt->d_name));
507     pEnt = readdir(pDir);
508     }
509    
510     if (closedir(pDir)) {
511     std::stringstream ss;
512     ss << "Failed to close directory `" << Dir << "`: ";
513     ss << strerror(errno);
514     throw Exception(ss.str());
515     }
516    
517     return fileList;
518     }
519    
520     void File::WalkDirectoryTree(std::string Dir, DirectoryWalker* pWalker) {
521     dmsg(2,("File: WalkDirectoryTree(Dir=%s)\n", Dir.c_str()));
522     File f = File(Dir);
523     if(!f.Exist()) throw Exception("Fail to stat `" + Dir + "`: " + f.GetErrorMsg());
524     if(!f.IsDirectory()) throw Exception("The specified path is not a directory: " + Dir);
525    
526     DirectoryWalkerMutex.Lock();
527     DirectoryWalkers.push_back(pWalker);
528     DWErrorMsg = "Failed to process directory tree: " + Dir;
529    
530     if (ftw(Dir.c_str(), FtwCallback, 10)) {
531     DirectoryWalkers.pop_back();
532     if (DirectoryWalkers.size() == 0) DirectoryWalkerMutex.Unlock();
533     throw Exception(DWErrorMsg);
534     }
535     DirectoryWalkers.pop_back();
536     if (DirectoryWalkers.size() == 0) DirectoryWalkerMutex.Unlock();
537     }
538    
539    
540     int File::FtwCallback(const char* fpath, const struct stat* sb, int typeflag) {
541     dmsg(2,("File: FtwCallback(fpath=%s)\n", fpath));
542     try {
543     if (typeflag == FTW_D) DirectoryWalkers.back()->DirectoryEntry(std::string(fpath));
544     else if (typeflag == FTW_F) DirectoryWalkers.back()->FileEntry(std::string(fpath));
545     } catch(Exception e) {
546     e.PrintMessage();
547     DWErrorMsg = e.Message();
548     return -1;
549     }
550    
551     return 0;
552     };
553     }

  ViewVC Help
Powered by ViewVC