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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1911 - (show 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 /***************************************************************************
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 #include <cstring>
24 #include <errno.h>
25 #include <sstream>
26 #include <sys/stat.h>
27
28 #include "Exception.h"
29 #include "global_private.h"
30
31 #if WIN32
32
33 /*
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 #else
445 #include <dirent.h>
446 #include <ftw.h>
447 #endif
448
449 namespace LinuxSampler {
450
451 char File::DirSeparator = '/';
452
453 Mutex File::DirectoryWalkerMutex;
454 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 return Status.st_size;
486 }
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