OpenSceneGraph/src/osgDB/FileUtils.cpp
2002-02-07 01:17:54 +00:00

396 lines
8.9 KiB
C++

#if defined(WIN32) &&!defined(__CYGWIN__)
#include <Io.h>
#include <Windows.h>
#include <Winbase.h>
#elif !defined(macintosh) // UNIX
#include <unistd.h>
#include <dlfcn.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <osg/Notify>
#include <osg/Node>
#include <osg/Geode>
#include <osg/Group>
#include <osgDB/FileUtils>
#include <osgDB/FileNameUtils>
#include <osgDB/Registry>
using namespace osg;
using namespace osgDB;
// follows is definition of strdup for compatibility under mac,
// However, I'd prefer to migrate all the findFindInPath tools to use
// std::string's and then be able to remove the following definition.
// My objective is to minimize the number of platform #ifdef's as they
// are source of potential bugs and developer confusion.
#ifdef macintosh
#ifndef strdup
inline static char* strdup(const char *src);
inline static char* strdup(const char *src)
{
char *ret = (char *) std::malloc(std::strlen(src) +1);
if(!ret) return NULL;
return std::strcpy(ret, src);
}
#endif
#endif
#define FILEUTILS_MAX_PATH_LENGTH 2048
#if defined(WIN32) &&!defined(__CYGWIN__)
char *PathDelimitor = ";";
static const char *s_default_file_path = ".;";
static const char *s_default_dso_path = "C:/Windows/System/;";
static char *s_filePath = ".;";
#elif macintosh
char *PathDelimitor = " ";
static const char *s_default_file_path = ":";
static const char *s_default_dso_path = ":";
static char *s_filePath = ":";
#elif __sgi
char *PathDelimitor = ":";
static const char *s_default_file_path = ".:";
static const char *s_default_dso_path = "/usr/lib32/:/usr/local/lib32/";
static char *s_filePath = ".:";
#else
char *PathDelimitor = ":";
static const char *s_default_file_path = ".:";
#if defined(__CYGWIN__)
static const char *s_default_dso_path = "/usr/lib/:/usr/local/lib/:";
#else
static const char *s_default_dso_path = "/usr/lib/:/usr/local/lib/:";
#endif // __CYGWIN__
static char *s_filePath = ".:";
#endif
#if defined(WIN32) &&!defined(__CYGWIN__)
#define F_OK 4
#endif
static bool s_filePathInitialized = false;
void osgDB::initFilePath( void )
{
char *ptr;
if( (ptr = getenv( "OSGFILEPATH" )) )
{
notify(DEBUG_INFO) << "osgDB::Init("<<ptr<<")"<<std::endl;
setFilePath( ptr );
}
else
{
notify(DEBUG_INFO) << "osgDB::Init(NULL)"<<std::endl;
}
s_filePathInitialized = true;
}
void osgDB::setFilePath( const char *_path )
{
char buff[FILEUTILS_MAX_PATH_LENGTH];
notify(DEBUG_INFO) << "In osgDB::setFilePath("<<_path<<")"<<std::endl;
buff[0] = 0;
if( s_filePath != s_default_file_path )
{
strcpy( buff, s_filePath );
}
strcat( buff, PathDelimitor );
strcat( buff, _path );
s_filePath = strdup( buff );
s_filePathInitialized = true;
}
const char* osgDB::getFilePath()
{
return s_filePath;
}
char *osgDB::findFileInPath( const char *_file, const char * filePath )
{
#ifdef macintosh
return (char *)_file;
#else
char pathbuff[FILEUTILS_MAX_PATH_LENGTH];
char *tptr, *tmppath;
char *path = 0L;
notify(DEBUG_INFO) << "FindFileInPath() : trying " << _file << " ...\n";
if( access( _file, F_OK ) == 0 )
{
return strdup(_file);
}
tptr = strdup( filePath );
tmppath = strtok( tptr, PathDelimitor );
do
{
sprintf( pathbuff, "%s/%s", tmppath, _file );
notify(DEBUG_INFO) << "FindFileInPath() : trying " << pathbuff << " ...\n";
if( access( pathbuff, F_OK ) == 0 ) break;
} while( (tmppath = strtok( 0, PathDelimitor )) );
if( tmppath != (char *)0L )
path = strdup( pathbuff );
::free(tptr);
if (path) notify( DEBUG_INFO ) << "FindFileInPath() : returning " << path << std::endl;
else notify( DEBUG_INFO ) << "FindFileInPath() : returning NULL" << std::endl;
return path;
#endif
}
char *osgDB::findFile( const char *file )
{
if (!file) return NULL;
if (!s_filePathInitialized) initFilePath();
char* newFileName = findFileInPath( file, s_filePath );
if (newFileName) return newFileName;
// need to check here to see if file has a path on it.
// now strip the file of an previous path if one exists.
std::string simpleFileName = getSimpleFileName(file);
newFileName = findFileInPath( simpleFileName.c_str(), s_filePath );
return newFileName;
}
/*
Order of precedence for
Under UNIX.
./
OSG_LD_LIBRARY_PATH
s_default_dso_path
LD_LIBRARY*_PATH
Under Windows
./
OSG_LD_LIBRARY_PATH
s_default_dso_path
PATH
*/
char *osgDB::findDSO( const char *name )
{
#ifndef macintosh
#if defined(__linux) || defined(__CYGWIN__)
if( access( name, F_OK ) == 0 )
{
if (name[0]!='/')
{
char pathbuff[FILEUTILS_MAX_PATH_LENGTH];
sprintf( pathbuff,"./%s", name );
return (char *)strdup(pathbuff);
}
else
{
return (char *)strdup(name);
}
}
#endif
char path[FILEUTILS_MAX_PATH_LENGTH];
char *ptr;
strcpy( path, "./" );
if((ptr = getenv( "OSG_LD_LIBRARY_PATH" )))
{
strcat( path, PathDelimitor );
strcat( path, ptr );
}
strcat( path, PathDelimitor );
strcat( path, s_default_dso_path );
#ifdef __sgi
// bloody mess see rld(1) man page
#if (_MIPS_SIM == _MIPS_SIM_ABI32)
if( (ptr = getenv( "LD_LIBRARY_PATH" )))
{
strcat( path, PathDelimitor );
strcat( path, ptr );
}
#elif (_MIPS_SIM == _MIPS_SIM_NABI32)
if( !(ptr = getenv( "LD_LIBRARYN32_PATH" )))
ptr = getenv( "LD_LIBRARY_PATH" );
if( ptr )
{
strcat( path, PathDelimitor );
strcat( path, ptr );
}
#elif (_MIPS_SIM == _MIPS_SIM_ABI64)
if( !(ptr = getenv( "LD_LIBRARYN32_PATH" )))
ptr = getenv( "LD_LIBRARY_PATH" );
if( ptr )
{
strcat( path, PathDelimitor );
strcat( path, ptr );
}
#endif
#elif defined(WIN32)
if ((ptr = getenv( "PATH" )))
{
notify(DEBUG_INFO) << "PATH = "<<ptr<<std::endl;
strcat( path, PathDelimitor );
strcat( path, ptr );
}
#else
if( (ptr = getenv( "LD_LIBRARY_PATH" )))
{
strcat( path, PathDelimitor );
strcat( path, ptr );
}
#endif
// check existance of dso assembled direct paths.
char* fileFound = NULL;
fileFound = findFileInPath( name , path );
if (fileFound) return fileFound;
// failed with direct paths,
// now try prepending the filename with "osgPlugins/"
char* prependosgPlugins = new char[strlen(name)+12];
strcpy(prependosgPlugins,"osgPlugins/");
strcat(prependosgPlugins,name);
fileFound = findFileInPath( prependosgPlugins , path );
delete prependosgPlugins;
return fileFound;
#else // defined macintosh
return NULL;
#endif
}
std::string osgDB::findFileInDirectory(const std::string& fileName,const std::string& dirName,bool caseInsensitive)
{
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)
{
if ((caseInsensitive && osgDB::equalCaseInsensitive(fileName,*itr)) ||
(fileName==*itr))
{
if (!needDirectoryName) return *itr;
else if (needFollowingBackslash) return dirName+'/'+*itr;
else return dirName+*itr;
}
}
return "";
}
#if defined(WIN32) &&!defined(__CYGWIN__)
#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;
}
#elif !defined(macintosh) // UNIX
#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