/[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 1910 - (show annotations) (download)
Fri Jun 5 14:22:20 2009 UTC (14 years, 10 months ago) by senoner
File size: 12554 byte(s)
* Added Instruments DB on Windows.
* Relative path support for DB file (stdalone and VST) not implemented yet

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

  ViewVC Help
Powered by ViewVC