2005-04-15 05:41:28 +08:00
|
|
|
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2005 Robert Osfield
|
2003-01-22 00:45:36 +08:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
2002-06-18 05:50:37 +08:00
|
|
|
|
2002-07-17 03:21:31 +08:00
|
|
|
// currently this impl is for _all_ platforms, execpt 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.
|
2002-06-18 05:50:37 +08:00
|
|
|
|
|
|
|
#if defined(WIN32) && !defined(__CYGWIN__)
|
|
|
|
#include <Io.h>
|
|
|
|
#include <Windows.h>
|
|
|
|
#include <Winbase.h>
|
2004-05-13 16:11:31 +08:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
2004-09-01 22:49:18 +08:00
|
|
|
#include <direct.h> // for _mkdir
|
2004-10-04 03:49:27 +08:00
|
|
|
|
2004-09-01 22:49:18 +08:00
|
|
|
#define mkdir(x,y) _mkdir((x))
|
2004-10-05 15:08:02 +08:00
|
|
|
#define stat64 _stati64
|
2004-09-01 22:49:18 +08:00
|
|
|
|
2002-06-18 05:50:37 +08:00
|
|
|
// set up for windows so acts just like unix access().
|
|
|
|
#define F_OK 4
|
2004-09-01 22:49:18 +08:00
|
|
|
|
|
|
|
|
2002-07-17 03:21:31 +08:00
|
|
|
#else // unix
|
2004-10-09 23:00:34 +08:00
|
|
|
|
2004-11-20 18:36:16 +08:00
|
|
|
#if defined( __APPLE__ ) || defined(__CYGWIN__) || defined(__FreeBSD__)
|
2004-10-09 23:00:34 +08:00
|
|
|
#define stat64 stat
|
|
|
|
#endif
|
|
|
|
|
2002-06-18 05:50:37 +08:00
|
|
|
#include <unistd.h>
|
2004-05-08 14:35:32 +08:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
2001-09-20 05:08:56 +08:00
|
|
|
#endif
|
2002-06-18 05:50:37 +08:00
|
|
|
|
2004-09-01 22:49:18 +08:00
|
|
|
// 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
|
|
|
|
|
2002-06-18 18:18:12 +08:00
|
|
|
#include <osg/Notify>
|
|
|
|
|
|
|
|
#include <osgDB/FileUtils>
|
|
|
|
#include <osgDB/FileNameUtils>
|
|
|
|
#include <osgDB/Registry>
|
|
|
|
|
2004-09-01 22:49:18 +08:00
|
|
|
#include <errno.h>
|
|
|
|
#include <stack>
|
|
|
|
|
|
|
|
bool osgDB::makeDirectory( const std::string &path )
|
|
|
|
{
|
|
|
|
if (path.empty())
|
|
|
|
{
|
|
|
|
osg::notify(osg::DEBUG_INFO) << "osgDB::makeDirectory(): cannot create an empty directory" << std::endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2004-10-03 16:50:56 +08:00
|
|
|
struct stat64 stbuf;
|
|
|
|
if( stat64( path.c_str(), &stbuf ) == 0 )
|
2004-09-01 22:49:18 +08:00
|
|
|
{
|
|
|
|
if( S_ISDIR(stbuf.st_mode))
|
|
|
|
return true;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
osg::notify(osg::DEBUG_INFO) << "osgDB::makeDirectory(): " <<
|
|
|
|
path << " already exists and is not a directory!" << std::endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string dir = path;
|
|
|
|
std::stack<std::string> paths;
|
|
|
|
while( true )
|
|
|
|
{
|
|
|
|
if( dir.empty() )
|
|
|
|
break;
|
|
|
|
|
2004-10-03 16:50:56 +08:00
|
|
|
if( stat64( dir.c_str(), &stbuf ) < 0 )
|
2004-09-01 22:49:18 +08:00
|
|
|
{
|
|
|
|
switch( errno )
|
|
|
|
{
|
|
|
|
case ENOENT:
|
|
|
|
case ENOTDIR:
|
|
|
|
paths.push( dir );
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2004-11-18 18:08:29 +08:00
|
|
|
osg::notify(osg::DEBUG_INFO) << "osgDB::makeDirectory(): " << strerror(errno) << std::endl;
|
2004-09-01 22:49:18 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dir = getFilePath(std::string(dir));
|
|
|
|
}
|
|
|
|
|
|
|
|
while( !paths.empty() )
|
|
|
|
{
|
|
|
|
std::string dir = paths.top();
|
|
|
|
|
|
|
|
if( mkdir( dir.c_str(), 0755 )< 0 )
|
|
|
|
{
|
2004-11-18 18:08:29 +08:00
|
|
|
osg::notify(osg::DEBUG_INFO) << "osgDB::makeDirectory(): " << strerror(errno) << std::endl;
|
2004-09-01 22:49:18 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
paths.pop();
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool osgDB::makeDirectoryForFile( const std::string &path )
|
|
|
|
{
|
|
|
|
return makeDirectory( getFilePath( path ));
|
|
|
|
}
|
2002-06-18 18:18:12 +08:00
|
|
|
|
2004-08-28 00:14:21 +08:00
|
|
|
void osgDB::convertStringPathIntoFilePathList(const std::string& paths,FilePathList& filepath)
|
|
|
|
{
|
|
|
|
#if defined(WIN32) && !defined(__CYGWIN__)
|
|
|
|
char delimitor = ';';
|
|
|
|
#else
|
|
|
|
char delimitor = ':';
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (!paths.empty())
|
|
|
|
{
|
|
|
|
std::string::size_type start = 0;
|
|
|
|
std::string::size_type end;
|
|
|
|
while ((end = paths.find_first_of(delimitor,start))!=std::string::npos)
|
|
|
|
{
|
|
|
|
filepath.push_back(std::string(paths,start,end-start));
|
|
|
|
start = end+1;
|
|
|
|
}
|
|
|
|
|
|
|
|
filepath.push_back(std::string(paths,start,std::string::npos));
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2002-06-18 05:50:37 +08:00
|
|
|
bool osgDB::fileExists(const std::string& filename)
|
|
|
|
{
|
|
|
|
return access( filename.c_str(), F_OK ) == 0;
|
|
|
|
}
|
|
|
|
|
2004-05-08 14:35:32 +08:00
|
|
|
osgDB::FileType osgDB::fileType(const std::string& filename)
|
|
|
|
{
|
2004-10-03 16:50:56 +08:00
|
|
|
struct stat64 fileStat;
|
|
|
|
if ( stat64(filename.c_str(), &fileStat) != 0 )
|
2004-05-08 14:35:32 +08:00
|
|
|
{
|
|
|
|
return FILE_NOT_FOUND;
|
2004-05-13 16:11:31 +08:00
|
|
|
} // end if
|
2004-05-13 21:37:55 +08:00
|
|
|
|
|
|
|
if ( fileStat.st_mode & S_IFDIR )
|
2004-05-13 16:11:31 +08:00
|
|
|
return DIRECTORY;
|
2004-05-13 21:37:55 +08:00
|
|
|
else if ( fileStat.st_mode & S_IFREG )
|
2004-05-08 14:35:32 +08:00
|
|
|
return REGULAR_FILE;
|
2004-05-13 21:37:55 +08:00
|
|
|
|
2004-05-13 16:11:31 +08:00
|
|
|
return FILE_NOT_FOUND;
|
2004-05-08 14:35:32 +08:00
|
|
|
}
|
|
|
|
|
2003-11-25 17:04:41 +08:00
|
|
|
std::string osgDB::findFileInPath(const std::string& filename, const FilePathList& filepath,CaseSensitivity caseSensitivity)
|
2002-06-18 05:50:37 +08:00
|
|
|
{
|
2003-11-06 12:08:53 +08:00
|
|
|
if (filename.empty())
|
|
|
|
return filename;
|
2002-06-18 05:50:37 +08:00
|
|
|
|
2005-02-11 17:58:30 +08:00
|
|
|
if (!isFileNameNativeStyle(filename))
|
|
|
|
return findFileInPath(convertFileNameToNativeStyle(filename), filepath, caseSensitivity);
|
|
|
|
|
2002-06-18 05:50:37 +08:00
|
|
|
|
|
|
|
for(FilePathList::const_iterator itr=filepath.begin();
|
|
|
|
itr!=filepath.end();
|
|
|
|
++itr)
|
|
|
|
{
|
2004-11-23 07:54:45 +08:00
|
|
|
osg::notify(osg::DEBUG_INFO) << "itr='" <<*itr<< "'\n";
|
|
|
|
std::string path = itr->empty() ? filename : *itr + '/'+ filename;
|
2002-06-18 05:50:37 +08:00
|
|
|
osg::notify(osg::DEBUG_INFO) << "FindFileInPath() : trying " << path << " ...\n";
|
2003-11-06 12:08:53 +08:00
|
|
|
if(fileExists(path))
|
|
|
|
{
|
|
|
|
osg::notify(osg::DEBUG_INFO) << "FindFileInPath() : USING " << path << "\n";
|
|
|
|
return path;
|
|
|
|
}
|
2003-11-25 17:04:41 +08:00
|
|
|
#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
|
|
|
|
|
2002-06-18 05:50:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return std::string();
|
|
|
|
}
|
|
|
|
|
2004-11-23 07:54:45 +08:00
|
|
|
|
2003-11-25 17:04:41 +08:00
|
|
|
std::string osgDB::findDataFile(const std::string& filename,CaseSensitivity caseSensitivity)
|
2004-11-22 22:10:12 +08:00
|
|
|
{
|
|
|
|
return findDataFile(filename,static_cast<ReaderWriter::Options*>(0),caseSensitivity);
|
|
|
|
}
|
|
|
|
|
2004-11-23 07:54:45 +08:00
|
|
|
OSGDB_EXPORT std::string osgDB::findDataFile(const std::string& filename,const ReaderWriter::Options* options, CaseSensitivity caseSensitivity)
|
2002-06-18 05:50:37 +08:00
|
|
|
{
|
|
|
|
if (filename.empty()) return filename;
|
2004-11-22 22:10:12 +08:00
|
|
|
|
2004-11-23 07:54:45 +08:00
|
|
|
if(fileExists(filename))
|
|
|
|
{
|
|
|
|
osg::notify(osg::DEBUG_INFO) << "FindFileInPath(" << filename << "): returning " << filename << std::endl;
|
|
|
|
return filename;
|
|
|
|
}
|
|
|
|
|
2004-11-22 22:10:12 +08:00
|
|
|
std::string fileFound;
|
|
|
|
|
|
|
|
if (options && !options->getDatabasePathList().empty())
|
|
|
|
{
|
|
|
|
fileFound = findFileInPath(filename, options->getDatabasePathList(), caseSensitivity);
|
|
|
|
if (!fileFound.empty()) return fileFound;
|
|
|
|
}
|
2002-06-18 05:50:37 +08:00
|
|
|
|
|
|
|
const FilePathList& filepath = Registry::instance()->getDataFilePathList();
|
2004-11-23 07:54:45 +08:00
|
|
|
if (!filepath.empty())
|
|
|
|
{
|
|
|
|
fileFound = findFileInPath(filename, filepath,caseSensitivity);
|
|
|
|
if (!fileFound.empty()) return fileFound;
|
|
|
|
}
|
|
|
|
|
2002-06-18 05:50:37 +08:00
|
|
|
|
|
|
|
// if a directory is included in the filename, get just the (simple) filename itself and try that
|
|
|
|
std::string simpleFileName = getSimpleFileName(filename);
|
|
|
|
if (simpleFileName!=filename)
|
|
|
|
{
|
2004-11-23 07:54:45 +08:00
|
|
|
|
|
|
|
if(fileExists(simpleFileName))
|
|
|
|
{
|
|
|
|
osg::notify(osg::DEBUG_INFO) << "FindFileInPath(" << filename << "): returning " << filename << std::endl;
|
|
|
|
return simpleFileName;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (options && !options->getDatabasePathList().empty())
|
|
|
|
{
|
|
|
|
fileFound = findFileInPath(simpleFileName, options->getDatabasePathList(), caseSensitivity);
|
|
|
|
if (!fileFound.empty()) return fileFound;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!filepath.empty())
|
|
|
|
{
|
|
|
|
fileFound = findFileInPath(simpleFileName, filepath,caseSensitivity);
|
|
|
|
if (!fileFound.empty()) return fileFound;
|
|
|
|
}
|
|
|
|
|
2002-06-18 05:50:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// return empty string.
|
|
|
|
return std::string();
|
|
|
|
}
|
|
|
|
|
2003-11-25 17:04:41 +08:00
|
|
|
std::string osgDB::findLibraryFile(const std::string& filename,CaseSensitivity caseSensitivity)
|
2002-06-18 05:50:37 +08:00
|
|
|
{
|
2003-11-06 12:08:53 +08:00
|
|
|
if (filename.empty())
|
|
|
|
return filename;
|
2002-06-18 05:50:37 +08:00
|
|
|
|
|
|
|
const FilePathList& filepath = Registry::instance()->getLibraryFilePathList();
|
|
|
|
|
2003-11-25 17:04:41 +08:00
|
|
|
std::string fileFound = findFileInPath(filename, filepath,caseSensitivity);
|
2003-11-06 12:08:53 +08:00
|
|
|
if (!fileFound.empty())
|
|
|
|
return fileFound;
|
2002-06-18 05:50:37 +08:00
|
|
|
|
2004-11-23 07:54:45 +08:00
|
|
|
if(fileExists(filename))
|
|
|
|
{
|
|
|
|
osg::notify(osg::DEBUG_INFO) << "FindFileInPath(" << filename << "): returning " << filename << std::endl;
|
|
|
|
return filename;
|
|
|
|
}
|
|
|
|
|
2002-06-18 05:50:37 +08:00
|
|
|
// if a directory is included in the filename, get just the (simple) filename itself and try that
|
|
|
|
std::string simpleFileName = getSimpleFileName(filename);
|
|
|
|
if (simpleFileName!=filename)
|
|
|
|
{
|
2003-11-25 17:04:41 +08:00
|
|
|
std::string fileFound = findFileInPath(simpleFileName, filepath,caseSensitivity);
|
2002-06-18 05:50:37 +08:00
|
|
|
if (!fileFound.empty()) return fileFound;
|
|
|
|
}
|
|
|
|
|
|
|
|
// failed with direct paths,
|
|
|
|
// now try prepending the filename with "osgPlugins/"
|
2003-11-25 17:04:41 +08:00
|
|
|
return findFileInPath("osgPlugins/"+simpleFileName,filepath,caseSensitivity);
|
2002-06-18 05:50:37 +08:00
|
|
|
}
|
|
|
|
|
2003-11-25 17:04:41 +08:00
|
|
|
std::string osgDB::findFileInDirectory(const std::string& fileName,const std::string& dirName,CaseSensitivity caseSensitivity)
|
2002-06-18 05:50:37 +08:00
|
|
|
{
|
|
|
|
bool needFollowingBackslash = false;
|
|
|
|
bool needDirectoryName = true;
|
|
|
|
osgDB::DirectoryContents dc;
|
|
|
|
|
|
|
|
if (dirName.empty())
|
|
|
|
{
|
|
|
|
dc = osgDB::getDirectoryContents(".");
|
|
|
|
needFollowingBackslash = false;
|
|
|
|
needDirectoryName = false;
|
|
|
|
}
|
|
|
|
else if (dirName=="." || dirName=="./" || dirName==".\\")
|
|
|
|
{
|
|
|
|
dc = osgDB::getDirectoryContents(".");
|
|
|
|
needFollowingBackslash = false;
|
|
|
|
needDirectoryName = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dc = osgDB::getDirectoryContents(dirName);
|
|
|
|
char lastChar = dirName[dirName.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)
|
|
|
|
{
|
2003-11-25 17:04:41 +08:00
|
|
|
if ((caseSensitivity==CASE_INSENSITIVE && osgDB::equalCaseInsensitive(fileName,*itr)) ||
|
2002-06-18 05:50:37 +08:00
|
|
|
(fileName==*itr))
|
|
|
|
{
|
|
|
|
if (!needDirectoryName) return *itr;
|
|
|
|
else if (needFollowingBackslash) return dirName+'/'+*itr;
|
|
|
|
else return dirName+*itr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
2002-06-26 04:47:42 +08:00
|
|
|
#if defined(WIN32) && !defined(__CYGWIN__)
|
2002-06-18 05:50:37 +08:00
|
|
|
#include <io.h>
|
|
|
|
#include <direct.h>
|
|
|
|
|
|
|
|
osgDB::DirectoryContents osgDB::getDirectoryContents(const std::string& dirName)
|
|
|
|
{
|
|
|
|
osgDB::DirectoryContents contents;
|
|
|
|
|
|
|
|
WIN32_FIND_DATA data;
|
|
|
|
HANDLE handle = FindFirstFile((dirName + "\\*").c_str(), &data);
|
|
|
|
if (handle != INVALID_HANDLE_VALUE)
|
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
|
|
|
contents.push_back(data.cFileName);
|
|
|
|
}
|
|
|
|
while (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
|
|
|
|
|
2004-08-28 00:14:21 +08:00
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// 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;
|
2004-08-29 07:04:47 +08:00
|
|
|
|
|
|
|
#if (_MIPS_SIM == _MIPS_SIM_ABI32)
|
2004-08-28 00:14:21 +08:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#elif defined(__CYGWIN__)
|
|
|
|
|
|
|
|
void osgDB::appendPlatformSpecificLibraryFilePaths(FilePathList& filepath)
|
|
|
|
{
|
|
|
|
char* ptr;
|
|
|
|
if ((ptr = getenv( "PATH" )))
|
|
|
|
{
|
|
|
|
convertStringPathIntoFilePathList(ptr,filepath);
|
|
|
|
}
|
|
|
|
|
|
|
|
convertStringPathIntoFilePathList("/usr/bin/:/usr/local/bin/",filepath);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#elif defined(WIN32)
|
|
|
|
|
|
|
|
void osgDB::appendPlatformSpecificLibraryFilePaths(FilePathList& filepath)
|
|
|
|
{
|
|
|
|
char* ptr;
|
|
|
|
if ((ptr = getenv( "PATH" )))
|
|
|
|
{
|
|
|
|
convertStringPathIntoFilePathList(ptr,filepath);
|
|
|
|
}
|
|
|
|
|
|
|
|
convertStringPathIntoFilePathList("C:/Windows/System/",filepath);
|
|
|
|
}
|
|
|
|
|
|
|
|
#elif defined(__APPLE__)
|
|
|
|
|
2004-08-28 00:52:23 +08:00
|
|
|
// #define COMPILE_COCOA_VERSION
|
2004-09-02 18:01:24 +08:00
|
|
|
#define COMPILE_CARBON_VERSION
|
2005-07-27 05:07:31 +08:00
|
|
|
// 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>
|
2004-08-28 00:52:23 +08:00
|
|
|
|
2005-07-27 05:07:31 +08:00
|
|
|
// 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);
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
|
|
|
// returns the absolute path to the main bundle
|
|
|
|
std::string GetApplicationBundlePath(CFBundleRef mainBundle)
|
|
|
|
{
|
|
|
|
std::string path;
|
|
|
|
CFURLRef urlRef = CFBundleCopyBundleURL(mainBundle);
|
|
|
|
if(urlRef)
|
2006-02-21 00:20:50 +08:00
|
|
|
{
|
2005-07-27 05:07:31 +08:00
|
|
|
path = GetPathFromCFURLRef(urlRef);
|
2006-02-21 00:20:50 +08:00
|
|
|
CFRelease(urlRef); // docs say we are responsible for releasing CFURLRef
|
|
|
|
}
|
2005-07-27 05:07:31 +08:00
|
|
|
return path;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string GetApplicationParentPath(CFBundleRef mainBundle)
|
|
|
|
{
|
|
|
|
return GetShortenedPath(GetApplicationBundlePath(mainBundle), 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string GetApplicationPluginsPath(CFBundleRef mainBundle)
|
|
|
|
{
|
|
|
|
std::string path;
|
|
|
|
CFURLRef urlRef = CFBundleCopyBuiltInPlugInsURL(mainBundle);
|
|
|
|
if(urlRef)
|
2006-02-21 00:20:50 +08:00
|
|
|
{
|
2005-07-27 05:07:31 +08:00
|
|
|
path = GetPathFromCFURLRef(urlRef);
|
2006-02-21 00:20:50 +08:00
|
|
|
CFRelease(urlRef);
|
|
|
|
}
|
2005-07-27 05:07:31 +08:00
|
|
|
return path;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string GetApplicationResourcesPath(CFBundleRef mainBundle)
|
|
|
|
{
|
|
|
|
std::string path;
|
|
|
|
CFURLRef urlRef = CFBundleCopyResourcesDirectoryURL(mainBundle);
|
|
|
|
if(urlRef)
|
2006-02-21 00:20:50 +08:00
|
|
|
{
|
2005-07-27 05:07:31 +08:00
|
|
|
path = GetPathFromCFURLRef(urlRef);
|
2006-02-21 00:20:50 +08:00
|
|
|
CFRelease(urlRef);
|
|
|
|
}
|
2005-07-27 05:07:31 +08:00
|
|
|
return path;
|
|
|
|
}
|
2004-08-28 00:52:23 +08:00
|
|
|
|
2004-08-28 00:14:21 +08:00
|
|
|
// The Cocoa version is about 10 lines of code.
|
|
|
|
// The Carbon version is noticably longer.
|
|
|
|
// Unfortunately, the Cocoa version requires -lobjc to be
|
|
|
|
// linked in when creating an executable.
|
|
|
|
// Rumor is that this will be done autmatically in gcc 3.5/Tiger,
|
|
|
|
// but for now, this will cause a lot of headaches for people
|
|
|
|
// who aren't familiar with this concept, so the Carbon version
|
|
|
|
// is preferable.
|
|
|
|
// But for the curious, both implementations are here.
|
|
|
|
// Note that if the Cocoa version is used, the file should be
|
|
|
|
// renamed to use the .mm extension to denote Objective-C++.
|
|
|
|
// And of course, you will need to link against Cocoa
|
|
|
|
|
2004-08-28 00:52:23 +08:00
|
|
|
#ifdef COMPILE_COCOA_VERSION
|
2004-08-28 00:14:21 +08:00
|
|
|
// OS X has preferred locations for where PlugIns should be located.
|
|
|
|
// This function will set this as the order to search:
|
|
|
|
// YourProgram.app/Contents/PlugIns
|
|
|
|
// ~/Library/Application Support/OpenSceneGraph/PlugIns
|
|
|
|
// /Library/Application Support/OpenSceneGraph/PlugIns
|
|
|
|
// /Network/Library/Application Support/OpenSceneGraph/PlugIns
|
|
|
|
//
|
|
|
|
// As a side effect of this function, if the application is not a
|
|
|
|
// bundle, the first place searched becomes
|
|
|
|
// YourProgram/PlugIns
|
|
|
|
//
|
|
|
|
// In principle, these other directories should be searched:
|
|
|
|
// ~/Library/Application Support/YourProgram/PlugIns
|
|
|
|
// /Library/Application Support/YourProgram/PlugIns
|
|
|
|
// /Network/Library/Application Support/TheProgram/PlugIns
|
|
|
|
// But I'm not going to worry about it for now because the
|
|
|
|
// bundle's PlugIns directory is supposed to be the preferred
|
|
|
|
// place for this anyway.
|
|
|
|
//
|
|
|
|
// Another directory that might be worth considering is
|
|
|
|
// the directory the program resides in,
|
|
|
|
// but I'm worried about multiplatform distribution.
|
|
|
|
// Because .so is used by other platforms like Linux, we
|
|
|
|
// could end up loading the wrong binary.
|
|
|
|
// I'm not sure how robust the current code is for this case.
|
|
|
|
// Assuming the program doesn't crash, will OSG move on to the
|
|
|
|
// next search directory, or just give up?
|
|
|
|
void osgDB::appendPlatformSpecificLibraryFilePaths(FilePathList& filepath)
|
|
|
|
{
|
|
|
|
char* ptr;
|
|
|
|
if ((ptr = getenv( "DYLD_LIBRARY_PATH" )) )
|
|
|
|
{
|
|
|
|
convertStringPathIntoFilePathList(ptr, filepath);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Since this is currently the only Objective-C code in the
|
|
|
|
// library, we need an autoreleasepool for obj-c memory management.
|
|
|
|
// If more Obj-C is added, we might move this pool to another
|
|
|
|
// location so it can be shared. Pools seem to be stackable,
|
|
|
|
// so I don't think there will be a problem if multiple pools
|
|
|
|
// exist at a time.
|
|
|
|
NSAutoreleasePool* mypool = [[NSAutoreleasePool alloc] init];
|
|
|
|
|
|
|
|
NSString* myBundlePlugInPath;
|
|
|
|
NSString* userSupportDir;
|
|
|
|
|
|
|
|
// This will grab the "official" bundle plug in path.
|
|
|
|
// It will be YourProgram.app/Contents/PlugIns (for App bundles)
|
|
|
|
// or YourProgram/PlugIns (for Unix executables)
|
|
|
|
myBundlePlugInPath = [[NSBundle mainBundle] builtInPlugInsPath];
|
|
|
|
|
|
|
|
// Now setup the other search paths
|
|
|
|
// Cocoa has a nice method for tilde expansion.
|
|
|
|
// There's probably a better way of getting this directory, but I
|
|
|
|
// can't find the call.
|
|
|
|
userSupportDir = [@"~/Library/Application Support/OpenSceneGraph/PlugIns" stringByExpandingTildeInPath];
|
|
|
|
|
|
|
|
// Can setup the remaining directories directly in C++
|
|
|
|
|
|
|
|
// Since Obj-C and C++ objects don't understand each other,
|
|
|
|
// the Obj-C strings must be converted down to C strings so
|
|
|
|
// C++ can make them into C++ strings.
|
|
|
|
filepath.push_back( [myBundlePlugInPath UTF8String] );
|
|
|
|
filepath.push_back( [userSupportDir UTF8String] );
|
|
|
|
|
|
|
|
filepath.push_back( "/Library/Application Support/OpenSceneGraph/PlugIns" );
|
|
|
|
filepath.push_back( "/Network/Library/Application Support/OpenSceneGraph/PlugIns" );
|
|
|
|
|
|
|
|
// Clean up the autorelease pool
|
|
|
|
[mypool release];
|
|
|
|
}
|
|
|
|
|
2004-08-28 00:52:23 +08:00
|
|
|
#elif defined(COMPILE_CARBON_VERSION)
|
|
|
|
|
2004-08-28 00:14:21 +08:00
|
|
|
// OS X has preferred locations for where PlugIns should be located.
|
|
|
|
// This function will set this as the order to search:
|
|
|
|
// YourProgram.app/Contents/PlugIns
|
|
|
|
// ~/Library/Application Support/OpenSceneGraph/PlugIns
|
|
|
|
// /Library/Application Support/OpenSceneGraph/PlugIns
|
|
|
|
// /Network/Library/Application Support/OpenSceneGraph/PlugIns
|
|
|
|
//
|
|
|
|
// In principle, these other directories should be searched:
|
|
|
|
// ~/Library/Application Support/YourProgram/PlugIns
|
|
|
|
// /Library/Application Support/YourProgram/PlugIns
|
|
|
|
// /Network/Library/Application Support/TheProgram/PlugIns
|
|
|
|
// But I'm not going to worry about it for now because the
|
|
|
|
// bundle's PlugIns directory is supposed to be the preferred
|
|
|
|
// place for this anyway.
|
|
|
|
//
|
|
|
|
// Another directory that might be worth considering is
|
|
|
|
// the directory the program resides in,
|
|
|
|
// but I'm worried about multiplatform distribution.
|
|
|
|
// Because .so is used by other platforms like Linux, we
|
|
|
|
// could end up loading the wrong binary.
|
|
|
|
// I'm not sure how robust the current code is for this case.
|
|
|
|
// Assuming the program doesn't crash, will OSG move on to the
|
|
|
|
// next search directory, or just give up?
|
|
|
|
void osgDB::appendPlatformSpecificLibraryFilePaths(FilePathList& filepath)
|
|
|
|
{
|
|
|
|
char* ptr;
|
|
|
|
if ((ptr = getenv( "DYLD_LIBRARY_PATH" )) )
|
|
|
|
{
|
|
|
|
convertStringPathIntoFilePathList(ptr, filepath);
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::string OSG_PLUGIN_PATH("/OpenSceneGraph/PlugIns");
|
|
|
|
CFURLRef url;
|
|
|
|
CFBundleRef myBundle;
|
|
|
|
FSRef f;
|
2005-06-13 19:14:42 +08:00
|
|
|
OSErr errCode;
|
2004-08-28 00:14:21 +08:00
|
|
|
|
|
|
|
// Start with the the Bundle PlugIns directory.
|
|
|
|
|
2005-07-27 05:07:31 +08:00
|
|
|
// Get the main bundle first. No need to retain or release it since
|
|
|
|
// we are not keeping a reference
|
2004-08-28 00:14:21 +08:00
|
|
|
myBundle = CFBundleGetMainBundle();
|
2005-07-27 05:07:31 +08:00
|
|
|
|
2004-08-28 00:14:21 +08:00
|
|
|
if(myBundle != NULL)
|
|
|
|
{
|
2005-07-27 05:07:31 +08:00
|
|
|
// CFBundleGetMainBundle will return a bundle ref even if
|
|
|
|
// the application isn't part of a bundle, so we need to check
|
|
|
|
// if the path to the bundle ends in ".app" to see if it is a
|
|
|
|
// proper application bundle. If it is, the plugins path is added
|
|
|
|
std::string bundlePath = GetApplicationBundlePath(myBundle);
|
|
|
|
if( bundlePath.substr(bundlePath.length() - 4, 4) == std::string(".app") )
|
|
|
|
filepath.push_back(GetApplicationPluginsPath(myBundle));
|
2004-08-28 00:14:21 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-08-28 00:19:05 +08:00
|
|
|
osg::notify( osg::DEBUG_INFO ) << "Couldn't find the Application Bundle" << std::endl;
|
2004-08-28 00:14:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Next, check the User's Application Support folder
|
|
|
|
errCode = FSFindFolder( kUserDomain, kApplicationSupportFolderType, kDontCreateFolder, &f );
|
|
|
|
if(noErr == errCode)
|
|
|
|
{
|
|
|
|
// Get the URL
|
|
|
|
url = CFURLCreateFromFSRef( 0, &f );
|
2005-07-27 05:07:31 +08:00
|
|
|
if(url)
|
2006-02-21 00:20:50 +08:00
|
|
|
{
|
2005-07-27 05:07:31 +08:00
|
|
|
filepath.push_back(GetPathFromCFURLRef(url) + OSG_PLUGIN_PATH);
|
2006-02-21 00:20:50 +08:00
|
|
|
CFRelease( url );
|
|
|
|
}
|
2005-07-27 04:31:43 +08:00
|
|
|
else
|
2005-07-27 05:07:31 +08:00
|
|
|
osg::notify( osg::DEBUG_INFO ) << "Couldn't create CFURLRef for User's application support Path" << std::endl;
|
|
|
|
|
2005-07-27 04:31:43 +08:00
|
|
|
url = NULL;
|
2004-08-28 00:14:21 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-08-28 00:19:05 +08:00
|
|
|
osg::notify( osg::DEBUG_INFO ) << "Couldn't find the User's Application Support Path" << std::endl;
|
2004-08-28 00:14:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Next, check the Local System's Application Support Folder
|
|
|
|
errCode = FSFindFolder( kLocalDomain, kApplicationSupportFolderType, kDontCreateFolder, &f );
|
|
|
|
if(noErr == errCode)
|
|
|
|
{
|
|
|
|
// Get the URL
|
|
|
|
url = CFURLCreateFromFSRef( 0, &f );
|
2005-07-27 05:07:31 +08:00
|
|
|
|
|
|
|
if(url)
|
2006-02-21 00:20:50 +08:00
|
|
|
{
|
2005-07-27 05:07:31 +08:00
|
|
|
filepath.push_back(GetPathFromCFURLRef(url) + OSG_PLUGIN_PATH);
|
2006-02-21 00:20:50 +08:00
|
|
|
CFRelease( url );
|
|
|
|
}
|
2005-07-27 04:31:43 +08:00
|
|
|
else
|
2005-07-27 05:07:31 +08:00
|
|
|
osg::notify( osg::DEBUG_INFO ) << "Couldn't create CFURLRef for local System's ApplicationSupport Path" << std::endl;
|
|
|
|
|
2005-07-27 04:31:43 +08:00
|
|
|
url = NULL;
|
2004-08-28 00:14:21 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-08-28 00:19:05 +08:00
|
|
|
osg::notify( osg::DEBUG_INFO ) << "Couldn't find the Local System's Application Support Path" << std::endl;
|
2004-08-28 00:14:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Finally, check the Network Application Support Folder
|
|
|
|
// This one has a likely chance of not existing so an error
|
|
|
|
// may be returned. Don't panic.
|
|
|
|
errCode = FSFindFolder( kNetworkDomain, kApplicationSupportFolderType, kDontCreateFolder, &f );
|
|
|
|
if(noErr == errCode)
|
|
|
|
{
|
|
|
|
// Get the URL
|
|
|
|
url = CFURLCreateFromFSRef( 0, &f );
|
2005-07-27 05:07:31 +08:00
|
|
|
|
|
|
|
if(url)
|
2006-02-21 00:20:50 +08:00
|
|
|
{
|
2005-07-27 05:07:31 +08:00
|
|
|
filepath.push_back(GetPathFromCFURLRef(url) + OSG_PLUGIN_PATH);
|
2006-02-21 00:20:50 +08:00
|
|
|
CFRelease( url );
|
|
|
|
}
|
2005-07-27 04:31:43 +08:00
|
|
|
else
|
2005-07-27 05:07:31 +08:00
|
|
|
osg::notify( osg::DEBUG_INFO ) << "Couldn't create CFURLRef for network Application Support Path" << std::endl;
|
|
|
|
|
|
|
|
url = NULL;
|
2004-08-28 00:14:21 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-06-13 19:14:42 +08:00
|
|
|
// had to comment out as it segfauls the OSX app otherwise
|
2004-09-14 23:05:16 +08:00
|
|
|
// osg::notify( osg::DEBUG_INFO ) << "Couldn't find the Network Application Support Path" << std::endl;
|
2004-08-28 00:14:21 +08:00
|
|
|
}
|
|
|
|
}
|
2004-08-28 00:52:23 +08:00
|
|
|
#else
|
|
|
|
void osgDB::appendPlatformSpecificLibraryFilePaths(FilePathList& filepath)
|
|
|
|
{
|
|
|
|
char* ptr;
|
|
|
|
if ((ptr = getenv( "DYLD_LIBRARY_PATH" )) )
|
|
|
|
{
|
|
|
|
convertStringPathIntoFilePathList(ptr, filepath);
|
|
|
|
}
|
|
|
|
}
|
2004-08-28 00:14:21 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
void osgDB::appendPlatformSpecificLibraryFilePaths(FilePathList& filepath)
|
|
|
|
{
|
|
|
|
|
|
|
|
char* ptr;
|
|
|
|
if( (ptr = getenv( "LD_LIBRARY_PATH" )) )
|
|
|
|
{
|
|
|
|
convertStringPathIntoFilePathList(ptr,filepath);
|
|
|
|
}
|
|
|
|
|
2005-06-13 19:14:42 +08:00
|
|
|
|
|
|
|
#if defined(__ia64__) || defined(__x86_64__)
|
|
|
|
convertStringPathIntoFilePathList("/usr/lib/:/usr/lib64/:/usr/local/lib/:/usr/local/lib64/",filepath);
|
|
|
|
#else
|
2004-08-28 00:14:21 +08:00
|
|
|
convertStringPathIntoFilePathList("/usr/lib/:/usr/local/lib/",filepath);
|
2005-06-13 19:14:42 +08:00
|
|
|
#endif
|
2004-08-28 00:14:21 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2005-07-27 05:07:31 +08:00
|
|
|
#ifdef __APPLE__
|
|
|
|
void osgDB::appendPlatformSpecificResourceFilePaths(FilePathList& filepath)
|
|
|
|
{
|
|
|
|
// Get the main application bundle
|
|
|
|
CFBundleRef mainBundle = CFBundleGetMainBundle();
|
|
|
|
|
|
|
|
if (mainBundle != NULL) {
|
|
|
|
// Get the parent directory and the resources directory
|
|
|
|
std::string bundlePath = GetApplicationBundlePath(mainBundle);
|
|
|
|
std::string resourcesPath = GetApplicationResourcesPath(mainBundle);
|
|
|
|
|
|
|
|
// check if application is really part of a .app bundle
|
|
|
|
if(bundlePath.substr(bundlePath.length() - 4, 4) == std::string(".app"))
|
|
|
|
{
|
|
|
|
if(resourcesPath != std::string(""))
|
|
|
|
filepath.push_back( resourcesPath );
|
|
|
|
|
|
|
|
std::string parentPath = GetShortenedPath(bundlePath, 1);
|
|
|
|
if(parentPath != std::string(""))
|
|
|
|
filepath.push_back( parentPath );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
osg::notify( osg::DEBUG_INFO ) << "Couldn't find the Application Bundle." << std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
2005-10-24 21:46:31 +08:00
|
|
|
void osgDB::appendPlatformSpecificResourceFilePaths(FilePathList& /*filepath*/)
|
2005-07-27 05:07:31 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
#endif
|
2004-08-28 00:14:21 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|