-
Notifications
You must be signed in to change notification settings - Fork 1.4k
/
Copy pathFileUtils.cpp
1298 lines (1106 loc) · 42.7 KB
/
FileUtils.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
// handle TCHAR type on various platforms
// #ifndef is inspired by https://svn.apache.org/repos/asf/logging/log4cxx/tags/v0_9_4/include/log4cxx/helpers/tchar.h
// defining type as plain char is from unzip.h, line 64
#ifndef TCHAR
typedef char TCHAR;
#endif
// currently this impl is for _all_ platforms, except as defined.
// the mac version will change soon to reflect the path scheme under osx, but
// for now, the above include is commented out, and the below code takes precedence.
#if defined(_WIN32) && !defined(__CYGWIN__)
#include <io.h>
#define WINBASE_DECLARE_GET_MODULE_HANDLE_EX
#include <windows.h>
#include <winbase.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <direct.h> // for _mkdir
#define mkdir(x,y) _mkdir((x))
#if !defined(__MINGW32__)
#define stat64 _stati64
#endif
// set up for windows so acts just like unix access().
#ifndef F_OK
#define F_OK 4
#endif
#ifdef _MSC_VER
#ifndef PATH_MAX
#define PATH_MAX MAX_PATH
#endif
#endif
#else // unix
#if defined( __APPLE__ )
// I'm not sure how we would handle this in raw Darwin
// without the AvailablilityMacros.
#include <AvailabilityMacros.h>
#include <libgen.h>
#include <mach-o/dyld.h>
//>OSG_IOS
//IOS includes
#include "TargetConditionals.h"
#include <sys/cdefs.h>
#if (TARGET_OS_IPHONE)
#include <Availability.h>
// workaround a bug which appears when compiling for SDK < 4.0 and for the simulator
#if defined(__IPHONE_4_0) && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0)
#define stat64 stat
#else
#if !TARGET_IPHONE_SIMULATOR
#define stat64 stat
#endif
#endif
#endif
//<OSG_IPHONE
// 10.5 defines stat64 so we can't use this #define
// By default, MAC_OS_X_VERSION_MAX_ALLOWED is set to the latest
// system the headers know about. So I will use this as the control
// variable. (MIN_ALLOWED is set low by default so it is
// unhelpful in this case.)
// Unfortunately, we can't use the label MAC_OS_X_VERSION_10_4
// for older OS's like Jaguar, Panther since they are not defined,
// so I am going to hardcode the number.
#if (MAC_OS_X_VERSION_MAX_ALLOWED <= 1040)
#define stat64 stat
#endif
#elif defined(__CYGWIN__) || defined(__FreeBSD__) || defined(__DragonFly__) || \
(defined(__hpux) && !defined(_LARGEFILE64_SOURCE))
#define stat64 stat
#endif
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#if defined(_DARWIN_FEATURE_64_BIT_INODE)
#define stat64 stat
#endif
#endif
#if defined(__ANDROID__)
#define stat64 stat
#endif
// set up _S_ISDIR()
#if !defined(S_ISDIR)
# if defined( _S_IFDIR) && !defined( __S_IFDIR)
# define __S_IFDIR _S_IFDIR
# endif
# define S_ISDIR(mode) (mode&__S_IFDIR)
#endif
#include <osg/Config>
#include <osgDB/ConvertUTF>
#include <osg/Notify>
#include <osgDB/FileUtils>
#include <osgDB/FileNameUtils>
#include <osgDB/Registry>
#include <errno.h>
#include <limits.h>
#include <string.h>
#include <stack>
namespace osgDB
{
#ifdef OSG_USE_UTF8_FILENAME
#define OSGDB_STRING_TO_FILENAME(s) osgDB::convertUTF8toUTF16(s)
#define OSGDB_FILENAME_TO_STRING(s) osgDB::convertUTF16toUTF8(s)
#define OSGDB_FILENAME_TEXT(x) L ## x
#define OSGDB_WINDOWS_FUNCT(x) x ## W
#define OSGDB_WINDOWS_FUNCT_STRING(x) #x "W"
typedef wchar_t filenamechar;
typedef std::wstring filenamestring;
#else
#define OSGDB_STRING_TO_FILENAME(s) s
#define OSGDB_FILENAME_TO_STRING(s) s
#define OSGDB_FILENAME_TEXT(x) x
#define OSGDB_WINDOWS_FUNCT(x) x ## A
#define OSGDB_WINDOWS_FUNCT_STRING(x) #x "A"
typedef char filenamechar;
typedef std::string filenamestring;
#endif
}
FILE* osgDB::fopen(const char* filename, const char* mode)
{
#ifdef OSG_USE_UTF8_FILENAME
return ::_wfopen(convertUTF8toUTF16(filename).c_str(), convertUTF8toUTF16(mode).c_str());
#else
return ::fopen(filename, mode);
#endif
}
bool osgDB::makeDirectory( const std::string &path )
{
if (path.empty())
{
OSG_DEBUG << "osgDB::makeDirectory(): cannot create an empty directory" << std::endl;
return false;
}
struct stat64 stbuf;
#ifdef OSG_USE_UTF8_FILENAME
if( _wstat64( OSGDB_STRING_TO_FILENAME(path).c_str(), &stbuf ) == 0 )
#else
if( stat64( path.c_str(), &stbuf ) == 0 )
#endif
{
if( S_ISDIR(stbuf.st_mode))
return true;
else
{
OSG_DEBUG << "osgDB::makeDirectory(): " <<
path << " already exists and is not a directory!" << std::endl;
return false;
}
}
std::stack<std::string> paths;
for(std::string dir = path;
!dir.empty();
dir = getFilePath(dir))
{
#ifdef OSG_USE_UTF8_FILENAME
if( _wstat64( OSGDB_STRING_TO_FILENAME(dir).c_str(), &stbuf ) < 0 )
#else
if( stat64( dir.c_str(), &stbuf ) < 0 )
#endif
{
switch( errno )
{
case ENOENT:
case ENOTDIR:
paths.push( dir );
break;
default:
OSG_DEBUG << "osgDB::makeDirectory(): " << strerror(errno) << std::endl;
return false;
}
}
}
while( !paths.empty() )
{
std::string dir = paths.top();
#if defined(_WIN32)
//catch drive name
if (dir.size() == 2 && dir.c_str()[1] == ':') {
paths.pop();
continue;
}
#endif
#ifdef OSG_USE_UTF8_FILENAME
if ( _wmkdir(OSGDB_STRING_TO_FILENAME(dir).c_str())< 0 )
#else
if( mkdir( dir.c_str(), 0755 )< 0 )
#endif
{
// Only return an error if the directory actually doesn't exist. It's possible that the directory was created
// by another thread or process
if (!osgDB::fileExists(dir))
{
OSG_DEBUG << "osgDB::makeDirectory(): " << strerror(errno) << std::endl;
return false;
}
}
paths.pop();
}
return true;
}
bool osgDB::makeDirectoryForFile( const std::string &path )
{
return makeDirectory( getFilePath( path ));
}
std::string osgDB::getCurrentWorkingDirectory( void )
{
// MAX_PATH/cwd inspired by unzip.cpp
#ifndef MAX_PATH
#define MAX_PATH 1024
#endif
TCHAR rootdir[MAX_PATH];
if(getcwd(rootdir,MAX_PATH-1))
{
return(rootdir);
}
return("");
}// osgDB::getCurrentWorkingDirectory
bool osgDB::setCurrentWorkingDirectory( const std::string &newCurrentWorkingDirectory )
{
if (newCurrentWorkingDirectory.empty())
{
OSG_DEBUG << "osgDB::setCurrentWorkingDirectory(): called with empty string." << std::endl;
return false;
}
#ifdef OSG_USE_UTF8_FILENAME
return _wchdir( OSGDB_STRING_TO_FILENAME(newCurrentWorkingDirectory).c_str()) == 0;
#else
return chdir( newCurrentWorkingDirectory.c_str()) == 0;
#endif
return true;
} // osgDB::setCurrentWorkingDirectory
void osgDB::convertStringPathIntoFilePathList(const std::string& paths,FilePathList& filepath)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
char delimiter = ';';
#else
char delimiter = ':';
#endif
if (!paths.empty())
{
std::string::size_type start = 0;
std::string::size_type end;
while ((end = paths.find_first_of(delimiter,start))!=std::string::npos)
{
filepath.push_back(std::string(paths,start,end-start));
start = end+1;
}
std::string lastPath(paths,start,std::string::npos);
if (!lastPath.empty())
filepath.push_back(lastPath);
}
}
bool osgDB::fileExists(const std::string& filename)
{
#ifdef OSG_USE_UTF8_FILENAME
return _waccess( OSGDB_STRING_TO_FILENAME(filename).c_str(), F_OK ) == 0;
#else
return access( filename.c_str(), F_OK ) == 0;
#endif
}
osgDB::FileType osgDB::fileType(const std::string& filename)
{
struct stat64 fileStat;
#ifdef OSG_USE_UTF8_FILENAME
if ( _wstat64(OSGDB_STRING_TO_FILENAME(filename).c_str(), &fileStat) != 0 )
#else
if ( stat64(filename.c_str(), &fileStat) != 0 )
#endif
{
return FILE_NOT_FOUND;
} // end if
if ( fileStat.st_mode & S_IFDIR )
return DIRECTORY;
else if ( fileStat.st_mode & S_IFREG )
return REGULAR_FILE;
return FILE_NOT_FOUND;
}
std::string osgDB::findFileInPath(const std::string& filename, const FilePathList& filepath,CaseSensitivity caseSensitivity)
{
if (filename.empty())
return filename;
if (!isFileNameNativeStyle(filename))
return findFileInPath(convertFileNameToNativeStyle(filename), filepath, caseSensitivity);
for(FilePathList::const_iterator itr=filepath.begin();
itr!=filepath.end();
++itr)
{
OSG_DEBUG << "itr='" <<*itr<< "'\n";
std::string path = itr->empty() ? filename : concatPaths(*itr, filename);
#ifdef _WIN32
// if combined file path exceeds MAX_PATH then ignore as it's not a legal path otherwise subsequent IO calls with this path may result in undefined behavior
if (path.length()>MAX_PATH) continue;
#endif
path = getRealPath(path);
OSG_DEBUG << "FindFileInPath() : trying " << path << " ...\n";
if(fileExists(path))
{
OSG_DEBUG << "FindFileInPath() : USING " << path << "\n";
return path;
}
#ifndef _WIN32
// windows already case insensitive so no need to retry..
else if (caseSensitivity==CASE_INSENSITIVE)
{
std::string foundfile = findFileInDirectory(filename,*itr,CASE_INSENSITIVE);
if (!foundfile.empty()) return foundfile;
}
#endif
}
return std::string();
}
std::string osgDB::findDataFile(const std::string& filename,CaseSensitivity caseSensitivity)
{
return findDataFile(filename,static_cast<Options*>(0),caseSensitivity);
}
OSGDB_EXPORT std::string osgDB::findDataFile(const std::string& filename,const Options* options, CaseSensitivity caseSensitivity)
{
return Registry::instance()->findDataFile(filename, options, caseSensitivity);
}
std::string osgDB::findLibraryFile(const std::string& filename,CaseSensitivity caseSensitivity)
{
return Registry::instance()->findLibraryFile(filename, osgDB::Registry::instance()->getOptions(), caseSensitivity);
}
std::string osgDB::findFileInDirectory(const std::string& fileName,const std::string& dirName,CaseSensitivity caseSensitivity)
{
bool needFollowingBackslash = false;
bool needDirectoryName = true;
osgDB::DirectoryContents dc;
std::string realDirName = dirName;
std::string realFileName = fileName;
// Skip case-insensitive recursion if on Windows
#ifdef _WIN32
bool win32 = true;
#else
bool win32 = false;
#endif
// If the fileName contains extra path information, make that part of the
// directory name instead
if (fileName != getSimpleFileName(fileName))
{
// See if we need to add a slash between the directory and file
if (realDirName.empty())
{
realDirName = getFilePath(fileName);
}
else if (realDirName=="." || realDirName=="./" || realDirName==".\\")
{
realDirName = "./" + getFilePath(fileName);
}
else
{
char lastChar = dirName[dirName.size()-1];
if ((lastChar == '/') || (lastChar == '\\'))
realDirName = dirName + getFilePath(fileName);
else
realDirName = dirName + "/" + getFilePath(fileName);
}
// Simplify the file name
realFileName = getSimpleFileName(fileName);
}
if (realDirName.size()>2)
{
char lastCharacter = realDirName[realDirName.size()-1];
bool trimLastCharacter = lastCharacter=='/' || lastCharacter=='\\';
if (trimLastCharacter)
{
realDirName.erase(realDirName.size()-1, 1);
OSG_DEBUG << "findFileInDirectory() Trimming last character of filepath, now realDirName="<<realDirName<<std::endl;
}
}
OSG_DEBUG << "findFileInDirectory() : looking for " << realFileName << " in " << realDirName << std::endl;
if (realDirName.empty())
{
dc = osgDB::getDirectoryContents(".");
needFollowingBackslash = false;
needDirectoryName = false;
}
else if (realDirName=="." || realDirName=="./" || realDirName==".\\")
{
dc = osgDB::getDirectoryContents(".");
needFollowingBackslash = false;
needDirectoryName = false;
}
else if (realDirName=="/")
{
dc = osgDB::getDirectoryContents("/");
needFollowingBackslash = false;
needDirectoryName = true;
}
else
{
// See if we're working in case insensitive mode, and that we're not
// using Windows (the recursive search is not needed in these
// cases)
if ((caseSensitivity == CASE_INSENSITIVE) && (!win32))
{
// Split the last path element from the directory name
std::string parentPath = getFilePath(realDirName);
std::string lastElement = getSimpleFileName(realDirName);
// See if we're already at the top level of the filesystem
if ((parentPath.empty()) && (!lastElement.empty()))
{
std::string directoryStringToUse = (realDirName[0]=='/' || realDirName[0]=='\\') ? std::string("/") : std::string(".");
// Search for the first path element (ignoring case) in
// the top-level directory
realDirName = findFileInDirectory(lastElement, directoryStringToUse,
CASE_INSENSITIVE);
dc = osgDB::getDirectoryContents(realDirName);
needFollowingBackslash = true;
needDirectoryName = true;
}
else
{
// Recursively search for the last path element (ignoring case)
// in the parent path
realDirName = findFileInDirectory(lastElement, parentPath,
CASE_INSENSITIVE);
dc = osgDB::getDirectoryContents(realDirName);
char lastChar = realDirName[realDirName.size()-1];
if (lastChar=='/') needFollowingBackslash = false;
else if (lastChar=='\\') needFollowingBackslash = false;
else needFollowingBackslash = true;
needDirectoryName = true;
}
}
else
{
// No need for recursive search if we're doing an exact comparison
dc = osgDB::getDirectoryContents(realDirName);
char lastChar = realDirName[realDirName.size()-1];
if (lastChar=='/') needFollowingBackslash = false;
else if (lastChar=='\\') needFollowingBackslash = false;
else needFollowingBackslash = true;
needDirectoryName = true;
}
}
for(osgDB::DirectoryContents::iterator itr=dc.begin();
itr!=dc.end();
++itr)
{
if ((caseSensitivity==CASE_INSENSITIVE && osgDB::equalCaseInsensitive(realFileName,*itr)) ||
(realFileName==*itr))
{
if (!needDirectoryName) return *itr;
else if (needFollowingBackslash) return realDirName+'/'+*itr;
else return realDirName+*itr;
}
}
return "";
}
/* This function has be taken from the VSG project */
std::string osgDB::executableFilePath()
{
std::string path;
#if defined(WIN32)
TCHAR buf[PATH_MAX + 1];
DWORD result = GetModuleFileName(NULL, buf, static_cast<DWORD>(std::size(buf) - 1));
if (result && result < std::size(buf))
path = buf;
#elif defined(__linux__)
std::vector<char> buffer(1024);
ssize_t len = 0;
while ((len = ::readlink("/proc/self/exe", buffer.data(), buffer.size())) == static_cast<ssize_t>(buffer.size()))
{
buffer.resize(buffer.size() * 2);
}
// add terminator to string.
buffer[len] = '\0';
return buffer.data();
#elif defined(__APPLE__)
# if TARGET_OS_MAC
char realPathName[PATH_MAX + 1];
char buf[PATH_MAX + 1];
uint32_t size = (uint32_t)sizeof(buf);
if (!_NSGetExecutablePath(buf, &size))
{
realpath(buf, realPathName);
path = realPathName;
}
# elif TARGET_IPHONE_SIMULATOR
// iOS, tvOS, or watchOS Simulator
// Not currently implemented
# elif TARGET_OS_MACCATALYST
// Mac's Catalyst (ports iOS API into Mac, like UIKit).
// Not currently implemented
# elif TARGET_OS_IPHONE
// iOS, tvOS, or watchOS device
// Not currently implemented
# else
# error "Unknown Apple platform"
# endif
#elif defined(__ANDROID__)
// Not currently implemented
#endif
return path;
}
static void appendInstallationLibraryFilePaths(osgDB::FilePathList& filepath)
{
#ifdef OSG_DEFAULT_LIBRARY_PATH
// Append the install prefix path to the library search path if configured
filepath.push_back(OSG_DEFAULT_LIBRARY_PATH);
#endif
}
#if defined(_WIN32) && !defined(__CYGWIN__)
#include <io.h>
#include <direct.h>
osgDB::DirectoryContents osgDB::getDirectoryContents(const std::string& dirName)
{
osgDB::DirectoryContents contents;
OSGDB_WINDOWS_FUNCT(WIN32_FIND_DATA) data;
HANDLE handle = OSGDB_WINDOWS_FUNCT(FindFirstFile)((OSGDB_STRING_TO_FILENAME(dirName) + OSGDB_FILENAME_TEXT("\\*")).c_str(), &data);
if (handle != INVALID_HANDLE_VALUE)
{
do
{
contents.push_back(OSGDB_FILENAME_TO_STRING(data.cFileName));
}
while (OSGDB_WINDOWS_FUNCT(FindNextFile)(handle, &data) != 0);
FindClose(handle);
}
return contents;
}
#else
#include <dirent.h>
osgDB::DirectoryContents osgDB::getDirectoryContents(const std::string& dirName)
{
osgDB::DirectoryContents contents;
DIR *handle = opendir(dirName.c_str());
if (handle)
{
dirent *rc;
while((rc = readdir(handle))!=NULL)
{
contents.push_back(rc->d_name);
}
closedir(handle);
}
return contents;
}
#endif // unix getDirectoryContexts
osgDB::DirectoryContents osgDB::getSortedDirectoryContents(const std::string& dirName)
{
osgDB::DirectoryContents filenames = osgDB::getDirectoryContents(dirName);
std::sort(filenames.begin(), filenames.end(), osgDB::FileNameComparator());
return filenames;
}
osgDB::DirectoryContents osgDB::expandWildcardsInFilename(const std::string& filename)
{
osgDB::DirectoryContents contents;
std::string dir = osgDB::getFilePath(filename);
std::string filenameOnly = dir.empty() ? filename : filename.substr(dir.length()+1, std::string::npos);
std::string left = filenameOnly.substr(0, filenameOnly.find('*'));
std::string right = filenameOnly.substr(filenameOnly.find('*')+1, std::string::npos);
if (dir.empty())
dir = osgDB::getCurrentWorkingDirectory();
osgDB::DirectoryContents dirContents = osgDB::getDirectoryContents(dir);
for (unsigned int i = 0; i < dirContents.size(); ++i)
{
std::string filenameInDir = dirContents[i];
if (filenameInDir == "." ||
filenameInDir == "..")
{
continue;
}
if ((filenameInDir.find(left) == 0 || left.empty()) &&
(filenameInDir.find(right) == filenameInDir.length() - right.length() || right.empty()))
{
contents.push_back( dir + osgDB::getNativePathSeparator() + filenameInDir );
}
}
return contents;
}
osgDB::CopyFileResult osgDB::copyFile(const std::string & source, const std::string & destination)
{
if (source.empty() || destination.empty())
{
OSG_INFO << "copyFile(): Empty file name." << std::endl;
return COPY_FILE_BAD_ARGUMENT;
}
// Check if source and destination are the same
if (source == destination || osgDB::getRealPath(source) == osgDB::getRealPath(destination))
{
OSG_INFO << "copyFile(): Source and destination point to the same file: source=" << source << ", destination=" << destination << std::endl;
return COPY_FILE_SOURCE_EQUALS_DESTINATION;
}
// Check if source file exists
if (!osgDB::fileExists(source))
{
OSG_INFO << "copyFile(): Source file does not exist: " << source << std::endl;
return COPY_FILE_SOURCE_MISSING;
}
// Open source file
osgDB::ifstream fin(source.c_str(), std::ios::in | std::ios::binary);
if (!fin)
{
OSG_NOTICE << "copyFile(): Can't read source file: " << source << std::endl;
return COPY_FILE_SOURCE_NOT_OPENED; // Return success since it's not an output error.
}
// Ensure the directory exists or else the FBX SDK will fail
if (!osgDB::makeDirectoryForFile(destination))
{
OSG_INFO << "Can't create directory for file '" << destination << "'. Copy may fail creating the file." << std::endl;
}
// Open destination file
osgDB::ofstream fout(destination.c_str(), std::ios::out | std::ios::binary | std::ios::trunc);
if (!fout)
{
OSG_NOTICE << "copyFile(): Can't write destination file: " << destination << std::endl;
return COPY_FILE_DESTINATION_NOT_OPENED;
}
// Copy file
const unsigned int BUFFER_SIZE = 10240;
osgDB::ifstream::char_type buffer[BUFFER_SIZE];
for(; fin.good() && fout.good() && !fin.eof(); )
{
fin.read(buffer, BUFFER_SIZE);
fout.write(buffer, fin.gcount());
}
if (!fout.good())
{
OSG_NOTICE << "copyFile(): Error writing destination file: " << destination << std::endl;
return COPY_FILE_WRITE_ERROR;
}
if (!fin.eof())
{
OSG_NOTICE << "copyFile(): Error reading source file: " << source << std::endl;
return COPY_FILE_READ_ERROR;
}
return COPY_FILE_OK;
}
bool osgDB::containsCurrentWorkingDirectoryReference(const FilePathList& paths)
{
const std::string cwd(".");
for(FilePathList::const_iterator itr = paths.begin();
itr != paths.end();
++itr)
{
if (itr->empty()) return true;
if (*itr==cwd) return true;
}
return false;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// Implementation of appendPlatformSpecificLibraryFilePaths(..)
//
#ifdef __sgi
void osgDB::appendPlatformSpecificLibraryFilePaths(FilePathList& filepath)
{
convertStringPathIntoFilePathList("/usr/lib32/:/usr/local/lib32/",filepath);
// bloody mess see rld(1) man page
char* ptr;
#if (_MIPS_SIM == _MIPS_SIM_ABI32)
if( (ptr = getenv( "LD_LIBRARY_PATH" )))
{
convertStringPathIntoFilePathList(ptr,filepath);
}
#elif (_MIPS_SIM == _MIPS_SIM_NABI32)
if( !(ptr = getenv( "LD_LIBRARYN32_PATH" )))
ptr = getenv( "LD_LIBRARY_PATH" );
if( ptr )
{
convertStringPathIntoFilePathList(ptr,filepath);
}
#elif (_MIPS_SIM == _MIPS_SIM_ABI64)
if( !(ptr = getenv( "LD_LIBRARY64_PATH" )))
ptr = getenv( "LD_LIBRARY_PATH" );
if( ptr )
{
convertStringPathIntoFilePathList(ptr,filepath);
}
#endif
appendInstallationLibraryFilePaths(filepath);
}
#elif defined(__CYGWIN__)
void osgDB::appendPlatformSpecificLibraryFilePaths(FilePathList& filepath)
{
char* ptr;
if ((ptr = getenv( "PATH" )))
{
convertStringPathIntoFilePathList(ptr,filepath);
}
appendInstallationLibraryFilePaths(filepath);
convertStringPathIntoFilePathList("/usr/bin/:/usr/local/bin/",filepath);
}
#elif defined(_WIN32)
void osgDB::appendPlatformSpecificLibraryFilePaths(FilePathList& filepath)
{
// See http://msdn2.microsoft.com/en-us/library/ms682586.aspx
// Safe DLL search mode changes the DLL search order to search for
// DLLs in the current directory after the system directories, instead
// of right after the application's directory. According to the article
// linked above, on Windows XP and Windows 2000, Safe DLL search mode
// is disabled by default. However, it is a good idea to enable it. We
// will search as if it was enabled.
// So if SafeDllSearchMode is enabled, the search order is as follows:
// 1. The directory from which the application loaded.
DWORD retval = 0;
const DWORD size = MAX_PATH;
filenamechar path[size];
retval = OSGDB_WINDOWS_FUNCT(GetModuleFileName)(NULL, path, size);
if (retval != 0 && retval < size)
{
filenamestring pathstr(path);
filenamestring executableDir(pathstr, 0,
pathstr.find_last_of(OSGDB_FILENAME_TEXT("\\/")));
convertStringPathIntoFilePathList(OSGDB_FILENAME_TO_STRING(executableDir), filepath);
}
else
{
OSG_WARN << "Could not get application directory "
"using Win32 API. It will not be searched." << std::endl;
}
// 2. The directory that the dll that contains this function is in.
// For static builds, this will be the executable directory.
#if defined(_MSC_VER)
// Requires use of the GetModuleHandleEx() function which is available only on Windows XP or higher.
// In order to allow execution on older versions, we load the function dynamically from the library and
// use it only if it's available.
OSGDB_WINDOWS_FUNCT(PGET_MODULE_HANDLE_EX) pGetModuleHandleEx = reinterpret_cast<OSGDB_WINDOWS_FUNCT(PGET_MODULE_HANDLE_EX)>
(GetProcAddress( GetModuleHandleA("kernel32.dll"), OSGDB_WINDOWS_FUNCT_STRING(GetModuleHandleEx)));
if( pGetModuleHandleEx )
{
HMODULE thisModule = 0;
static filenamechar static_variable = 0; // Variable that is located in DLL address space.
if( pGetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, &static_variable, &thisModule) )
{
retval = OSGDB_WINDOWS_FUNCT(GetModuleFileName)(thisModule, path, size);
if (retval != 0 && retval < size)
{
filenamestring pathstr(path);
filenamestring dllDir(pathstr, 0,
pathstr.find_last_of(OSGDB_FILENAME_TEXT("\\/")));
convertStringPathIntoFilePathList(OSGDB_FILENAME_TO_STRING(dllDir), filepath);
}
else
{
OSG_WARN << "Could not get dll directory "
"using Win32 API. It will not be searched." << std::endl;
}
FreeLibrary(thisModule);
}
else
{
OSG_WARN << "Could not get dll module handle "
"using Win32 API. Dll directory will not be searched." << std::endl;
}
}
#endif
// 3. The system directory. Use the GetSystemDirectory function to
// get the path of this directory.
filenamechar systemDir[(UINT)size];
retval = OSGDB_WINDOWS_FUNCT(GetSystemDirectory)(systemDir, (UINT)size);
if (retval != 0 && retval < size)
{
convertStringPathIntoFilePathList(OSGDB_FILENAME_TO_STRING(systemDir),
filepath);
}
else
{
OSG_WARN << "Could not get system directory using "
"Win32 API, using default directory." << std::endl;
convertStringPathIntoFilePathList("C:\\Windows\\System32",
filepath);
}
// 4. The 16-bit system directory. There is no function that obtains
// the path of this directory, but it is searched.
// 5. The Windows directory. Use the GetWindowsDirectory function to
// get the path of this directory.
filenamechar windowsDir[(UINT)size];
retval = OSGDB_WINDOWS_FUNCT(GetWindowsDirectory)(windowsDir, (UINT)size);
if (retval != 0 && retval < size)
{
convertStringPathIntoFilePathList(std::string(OSGDB_FILENAME_TO_STRING(windowsDir)) +
"\\System", filepath);
convertStringPathIntoFilePathList(OSGDB_FILENAME_TO_STRING(windowsDir),
filepath);
}
else
{
OSG_WARN << "Could not get Windows directory using "
"Win32 API, using default directory." << std::endl;
convertStringPathIntoFilePathList("C:\\Windows", filepath);
convertStringPathIntoFilePathList("C:\\Windows\\System", filepath);
}
// 6. The current directory.
convertStringPathIntoFilePathList(".", filepath);
// 7. The directories that are listed in the PATH environment
// variable. Note that this does not include the per-application
// path specified by the App Paths registry key.
filenamechar* ptr;
#ifdef OSG_USE_UTF8_FILENAME
if ((ptr = _wgetenv(OSGDB_FILENAME_TEXT("PATH"))))
#else
if ((ptr = getenv("PATH")))
#endif
{
// Note that on any sane Windows system, some of the paths above
// will also be on the PATH (the values gotten in systemDir and
// windowsDir), but the DLL search goes sequentially and stops
// when a DLL is found, so I see no point in removing duplicates.
convertStringPathIntoFilePathList(OSGDB_FILENAME_TO_STRING(ptr), filepath);
}
appendInstallationLibraryFilePaths(filepath);
}
#elif defined(__APPLE__)
#if (TARGET_OS_IPHONE) || (MAC_OS_X_VERSION_MIN_REQUIRED >= 1080)
#define COMPILE_COCOA_VERSION
#else
#define COMPILE_CARBON_VERSION
#endif
// WARNING: Cocoa version is currently untested.
#ifdef COMPILE_COCOA_VERSION
#include <Foundation/Foundation.h>
#endif
#ifdef COMPILE_CARBON_VERSION
#include <CoreServices/CoreServices.h>
#include <CoreFoundation/CoreFoundation.h>
#include <Carbon/Carbon.h>
#endif
#include <iostream>
// These functions are local to FileUtils.cpp and not exposed to the API
// returns the path string except for numToShorten directories stripped off the end
std::string GetShortenedPath(std::string path, int numToShorten)
{
unsigned int i = path.length() - 1;
if(path[i] == '/') i--;
while(i > 1 && numToShorten)
{
if(path[i] == '/')
numToShorten--;
i--;
}
return path.substr(0,i + 1);
}
// returns an absolute (POSIX on MacOS X) path from a CFURLRef
std::string GetPathFromCFURLRef(CFURLRef urlRef)
{
char buffer[1024];
std::string path;
if(CFURLGetFileSystemRepresentation(urlRef, true, (UInt8*)buffer, 1024))
path = std::string(buffer);