/* ----------------------------------------------------------------------------- This source file is part of OGRE (Object-oriented Graphics Rendering Engine) For the latest info, see http://www.ogre3d.org/ Copyright (c) 2000-2005 The OGRE Team Also see acknowledgements in Readme.html This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA, or go to http://www.gnu.org/copyleft/lesser.txt. ----------------------------------------------------------------------------- */ #include "OgreStableHeaders.h" #include "OgreFileSystem.h" #include "OgreLogManager.h" #include "OgreException.h" #include "OgreStringVector.h" #include "OgreRoot.h" #include #include #if OGRE_PLATFORM == OGRE_PLATFORM_LINUX || OGRE_PLATFORM == OGRE_PLATFORM_APPLE # include "OgreSearchOps.h" # include # define MAX_PATH MAXPATHLEN #endif #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 # include # include # include #endif namespace Ogre { //----------------------------------------------------------------------- FileSystemArchive::FileSystemArchive(const String& name, const String& archType ) : Archive(name, archType) { } //----------------------------------------------------------------------- bool FileSystemArchive::isCaseSensitive(void) const { #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 return false; #else return true; #endif } //----------------------------------------------------------------------- void FileSystemArchive::findFiles(const String& pattern, bool recursive, StringVector* simpleList, FileInfoList* detailList, const String& currentDir) { // parsing requires locking due to saved returns OGRE_LOCK_AUTO_MUTEX long lHandle, res; struct _finddata_t tagData; lHandle = _findfirst(pattern.c_str(), &tagData); res = 0; while (lHandle != -1 && res != -1) { if(!(tagData.attrib & _A_SUBDIR)) { if (simpleList) { simpleList->push_back(currentDir + tagData.name); } else if (detailList) { FileInfo fi; fi.archive = this; fi.filename = currentDir + tagData.name; fi.basename = tagData.name; fi.path = currentDir; fi.compressedSize = tagData.size; fi.uncompressedSize = tagData.size; detailList->push_back(fi); } } res = _findnext( lHandle, &tagData ); } // Close if we found any files if(lHandle != -1) { _findclose(lHandle); } // Now find directories if (recursive) { lHandle = _findfirst("*", &tagData); res = 0; while (lHandle != -1 && res != -1) { if((tagData.attrib & _A_SUBDIR) && strcmp(tagData.name, ".") && strcmp(tagData.name, "..")) { // recurse String dir = currentDir + tagData.name + "/"; pushDirectory(tagData.name); findFiles(pattern, recursive, simpleList, detailList, dir); popDirectory(); } res = _findnext( lHandle, &tagData ); } // Close if we found any files if(lHandle != -1) { _findclose(lHandle); } } } //----------------------------------------------------------------------- void FileSystemArchive::changeDirectory(const String& dir) const { if(chdir(dir.c_str()) == -1) { OGRE_EXCEPT(Exception::ERR_FILE_NOT_FOUND, "Cannot open requested directory " + dir, "FileSystemArchive::changeDirectory"); } } //----------------------------------------------------------------------- void FileSystemArchive::pushDirectory(const String& dir) const { // get current directory and push it onto the stack getcwd(mTmpPath, OGRE_MAX_PATH); mDirectoryStack.push_back(String(mTmpPath)); changeDirectory(dir); } //----------------------------------------------------------------------- void FileSystemArchive::popDirectory(void) const { if (mDirectoryStack.empty()) { OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "No directories left in the stack.", "FileSystemArchive::popDirectory"); } changeDirectory(mDirectoryStack.back()); mDirectoryStack.pop_back(); } //----------------------------------------------------------------------- FileSystemArchive::~FileSystemArchive() { unload(); } //----------------------------------------------------------------------- void FileSystemArchive::load() { mBasePath = mName; // Check we can change to it pushDirectory(mBasePath); // return to previous popDirectory(); } //----------------------------------------------------------------------- void FileSystemArchive::unload() { // nothing to see here, move along } //----------------------------------------------------------------------- DataStreamPtr FileSystemArchive::open(const String& filename) const { // directory change requires locking due to saved returns OGRE_LOCK_AUTO_MUTEX pushDirectory(mBasePath); // Use filesystem to determine size // (quicker than streaming to the end and back) struct stat tagStat; int ret = stat(filename.c_str(), &tagStat); assert(ret == 0 && "Problem getting file size" ); // Always open in binary mode std::ifstream *origStream = new std::ifstream(); origStream->open(filename.c_str(), std::ios::in | std::ios::binary); popDirectory(); /// Construct return stream, tell it to delete on destroy FileStreamDataStream* stream = new FileStreamDataStream(filename, origStream, tagStat.st_size, true); return DataStreamPtr(stream); } //----------------------------------------------------------------------- StringVectorPtr FileSystemArchive::list(bool recursive) { // directory change requires locking due to saved returns OGRE_LOCK_AUTO_MUTEX pushDirectory(mBasePath); StringVectorPtr ret(new StringVector()); findFiles("*", recursive, ret.getPointer(), 0); popDirectory(); return ret; } //----------------------------------------------------------------------- FileInfoListPtr FileSystemArchive::listFileInfo(bool recursive) { // directory change requires locking due to saved returns OGRE_LOCK_AUTO_MUTEX pushDirectory(mBasePath); FileInfoListPtr ret(new FileInfoList()); findFiles("*", recursive, 0, ret.getPointer()); popDirectory(); return ret; } //----------------------------------------------------------------------- StringVectorPtr FileSystemArchive::find(const String& pattern, bool recursive) { // directory change requires locking due to saved returns OGRE_LOCK_AUTO_MUTEX pushDirectory(mBasePath); StringVectorPtr ret(new StringVector()); findFiles(pattern, recursive, ret.getPointer(), 0); popDirectory(); return ret; } //----------------------------------------------------------------------- FileInfoListPtr FileSystemArchive::findFileInfo(const String& pattern, bool recursive) { // directory change requires locking due to saved returns OGRE_LOCK_AUTO_MUTEX pushDirectory(mBasePath); FileInfoListPtr ret(new FileInfoList()); findFiles(pattern, recursive, 0, ret.getPointer()); popDirectory(); return ret; } //----------------------------------------------------------------------- bool FileSystemArchive::exists(const String& filename) { // directory change requires locking due to saved returns OGRE_LOCK_AUTO_MUTEX bool ret; pushDirectory(mBasePath); struct stat tagStat; ret = (stat(filename.c_str(), &tagStat) == 0); popDirectory(); return ret; } //----------------------------------------------------------------------- const String& FileSystemArchiveFactory::getType(void) const { static String name = "FileSystem"; return name; } }