//----------------------------------------------------------------------- bool FileSystemArchive::exists(const String& filename) { String full_path = concatenate_path(mName, filename); struct stat tagStat; bool ret = (stat(full_path.c_str(), &tagStat) == 0); // stat will return true if the filename is absolute, but we need to check // the file is actually in this archive if (ret && is_absolute_path(filename.c_str())) { // only valid if full path starts with our base #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 // case insensitive on windows String lowerCaseName = mName; StringUtil::toLowerCase(lowerCaseName); ret = Ogre::StringUtil::startsWith(full_path, lowerCaseName, true); #else // case sensitive ret = Ogre::StringUtil::startsWith(full_path, mName, false); #endif } return ret; }
//--------------------------------------------------------------------- DataStreamPtr FileSystemArchive::create(const String& filename) const { if (isReadOnly()) { OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Cannot create a file in a read-only archive", "FileSystemArchive::remove"); } String full_path = concatenate_path(mName, filename); // Always open in binary mode // Also, always include reading std::ios::openmode mode = std::ios::out | std::ios::binary; std::fstream* rwStream = OGRE_NEW_T(std::fstream, MEMCATEGORY_GENERAL)(); rwStream->open(full_path.c_str(), mode); // Should check ensure open succeeded, in case fail for some reason. if (rwStream->fail()) { OGRE_DELETE_T(rwStream, basic_fstream, MEMCATEGORY_GENERAL); OGRE_EXCEPT(Exception::ERR_FILE_NOT_FOUND, "Cannot open file: " + filename, "FileSystemArchive::create"); } /// Construct return stream, tell it to delete on destroy FileStreamDataStream* stream = OGRE_NEW FileStreamDataStream(filename, rwStream, 0, true); return DataStreamPtr(stream); }
//----------------------------------------------------------------------- DataStreamPtr FileSystemArchive::open(const String& filename) const { #if (_MSC_VER >= 1400) // std::locale langLocale(""); // std::locale::global(langLocale); setlocale( LC_CTYPE, "" ); #endif String full_path = concatenate_path(mName, filename); // Use filesystem to determine size // (quicker than streaming to the end and back) struct stat tagStat; int ret = stat(full_path.c_str(), &tagStat); assert(ret == 0 && "Problem getting file size" ); // Always open in binary mode std::ifstream *origStream = OGRE_NEW_T(std::ifstream, MEMCATEGORY_GENERAL)(); origStream->open(full_path.c_str(), std::ios::in | std::ios::binary); // Should check ensure open succeeded, in case fail for some reason. if (origStream->fail()) { OGRE_DELETE_T(origStream, basic_ifstream, MEMCATEGORY_GENERAL); OGRE_EXCEPT(Exception::ERR_FILE_NOT_FOUND, "Cannot open file: " + filename, "FileSystemArchive::open"); } /// Construct return stream, tell it to delete on destroy FileStreamDataStream* stream = OGRE_NEW FileStreamDataStream(filename, origStream, tagStat.st_size, true); return DataStreamPtr(stream); }
//----------------------------------------------------------------------- DataStreamPtr FileSystemArchive::open(const String& filename, bool readOnly) const { String full_path = concatenate_path(mName, filename); // Use filesystem to determine size // (quicker than streaming to the end and back) struct stat tagStat; stat(full_path.c_str(), &tagStat); // Always open in binary mode std::ifstream *origStream = OGRE_NEW_T(std::ifstream, MEMCATEGORY_GENERAL)(); origStream->open(full_path.c_str(), std::ios::in | std::ios::binary); // Should check ensure open succeeded, in case fail for some reason. if (origStream->fail()) { OGRE_DELETE_T(origStream, basic_ifstream, MEMCATEGORY_GENERAL); OGRE_EXCEPT(Ogre::Exception::ERR_FILE_NOT_FOUND, "Cannot open file: " + filename, "FileSystemArchive::open"); } // Construct return stream, tell it to delete on destroy FileStreamDataStream* stream = OGRE_NEW FileStreamDataStream(filename, origStream, tagStat.st_size, true); return DataStreamPtr(stream); }
DataStreamPtr WriteableFileSystemArchive::open(const String& filename) const { String full_path = concatenate_path(mName, filename); // Use filesystem to determine size // (quicker than streaming to the end and back) struct stat tagStat; int ret = stat(full_path.c_str(), &tagStat); assert(ret == 0 && "Problem getting file size" ); // Always open in binary mode std::fstream *origStream = new std::fstream(); origStream->open(full_path.c_str(), std::ios::in | std::ios::out | std::ios::binary); // Should check ensure open succeeded, in case fail for some reason. if (origStream->fail()) { delete origStream; OGRE_EXCEPT(Exception::ERR_FILE_NOT_FOUND, "Cannot open file: " + filename, "WriteableFileSystemArchive::open"); } /// Construct return stream, tell it to delete on destroy WriteableFileStreamDataStream* stream = new WriteableFileStreamDataStream(filename, origStream, tagStat.st_size, true); return DataStreamPtr(stream); }
Ogre::DataStreamPtr OMEFileSystemArchive::open(const Ogre::String& filename, bool readOnly) const { Ogre::String full_path = concatenate_path(mName, filename); // Use filesystem to determine size // (quicker than streaming to the end and back) struct stat tagStat; int ret = stat(full_path.c_str(), &tagStat); assert(ret == 0 && "Problem getting file size" ); (void)ret; // Silence warning // Always open in binary mode // Also, always include reading std::ios::openmode mode = std::ios::in | std::ios::binary; std::istream* baseStream = 0; std::ifstream* roStream = 0; std::fstream* rwStream = 0; if (!readOnly && isReadOnly()) { mode |= std::ios::out; rwStream = OGRE_NEW_T(std::fstream, Ogre::MEMCATEGORY_GENERAL)(); rwStream->open(full_path.c_str(), mode); baseStream = rwStream; } else { roStream = OGRE_NEW_T(std::ifstream, Ogre::MEMCATEGORY_GENERAL)(); roStream->open(full_path.c_str(), mode); baseStream = roStream; } // Should check ensure open succeeded, in case fail for some reason. if (baseStream->fail()) { OGRE_DELETE_T(roStream, basic_ifstream, Ogre::MEMCATEGORY_GENERAL); OGRE_DELETE_T(rwStream, basic_fstream, Ogre::MEMCATEGORY_GENERAL); OGRE_EXCEPT(Ogre::Exception::ERR_FILE_NOT_FOUND, "Cannot open file: " + filename, "FileSystemArchive::open"); } /// Construct return stream, tell it to delete on destroy Ogre::FileStreamDataStream* stream = 0; if (rwStream) { // use the writeable stream stream = OGRE_NEW Ogre::FileStreamDataStream(filename, rwStream, (size_t)tagStat.st_size, true); } else { // read-only stream Ogre::String newName = mName + ":" + filename; stream = OGRE_NEW Ogre::FileStreamDataStream(newName, roStream, (size_t)tagStat.st_size, true); } return Ogre::DataStreamPtr(stream); }
//--------------------------------------------------------------------- void FileSystemArchive::remove(const String& filename) const { if (isReadOnly()) { OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Cannot remove a file from a read-only archive", "FileSystemArchive::remove"); } String full_path = concatenate_path(mName, filename); ::remove(full_path.c_str()); }
//----------------------------------------------------------------------- void FileSystemArchive::load() { OGRE_LOCK_AUTO_MUTEX // test to see if this folder is writeable String testPath = concatenate_path(mName, "__testwrite.ogre"); std::ofstream writeStream; writeStream.open(testPath.c_str()); if (writeStream.fail()) mReadOnly = true; else { mReadOnly = false; writeStream.close(); ::remove(testPath.c_str()); } }
//--------------------------------------------------------------------- time_t FileSystemArchive::getModifiedTime(const String& filename) { String full_path = concatenate_path(mName, filename); struct stat tagStat; bool ret = (stat(full_path.c_str(), &tagStat) == 0); if (ret) { return tagStat.st_mtime; } else { return 0; } }
//----------------------------------------------------------------------- bool FileSystemArchive::exists(const String& filename) { String full_path = concatenate_path(mName, filename); struct stat tagStat; bool ret = (stat(full_path.c_str(), &tagStat) == 0); // stat will return true if the filename is absolute, but we need to check // the file is actually in this archive if (ret && is_absolute_path(filename.c_str())) { // only valid if full path starts with our base ret = Ogre::StringUtil::startsWith(full_path, mName); } return ret; }
//----------------------------------------------------------------------- void FileSystemArchive::findFiles(const String& pattern, bool recursive, bool dirs, StringVector* simpleList, FileInfoList* detailList) const { intptr_t lHandle, res; struct _finddata_t tagData; // pattern can contain a directory name, separate it from mask size_t pos1 = pattern.rfind ('/'); size_t pos2 = pattern.rfind ('\\'); if (pos1 == pattern.npos || ((pos2 != pattern.npos) && (pos1 < pos2))) pos1 = pos2; String directory; if (pos1 != pattern.npos) directory = pattern.substr (0, pos1 + 1); String full_pattern = concatenate_path(mName, pattern); lHandle = _findfirst(full_pattern.c_str(), &tagData); res = 0; while (lHandle != -1 && res != -1) { if ((dirs == ((tagData.attrib & _A_SUBDIR) != 0)) && ( !msIgnoreHidden || (tagData.attrib & _A_HIDDEN) == 0 ) && (!dirs || !is_reserved_dir (tagData.name))) { if (simpleList) { simpleList->push_back(directory + tagData.name); } else if (detailList) { FileInfo fi; fi.archive = this; fi.filename = directory + tagData.name; fi.basename = tagData.name; fi.path = directory; 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) { String base_dir = mName; if (!directory.empty ()) { base_dir = concatenate_path(mName, directory); // Remove the last '/' base_dir.erase (base_dir.length () - 1); } base_dir.append ("/*"); // Remove directory name from pattern String mask ("/"); if (pos1 != pattern.npos) mask.append (pattern.substr (pos1 + 1)); else mask.append (pattern); lHandle = _findfirst(base_dir.c_str (), &tagData); res = 0; while (lHandle != -1 && res != -1) { if ((tagData.attrib & _A_SUBDIR) && ( !msIgnoreHidden || (tagData.attrib & _A_HIDDEN) == 0 ) && !is_reserved_dir (tagData.name)) { // recurse base_dir = directory; base_dir.append (tagData.name).append (mask); findFiles(base_dir, recursive, dirs, simpleList, detailList); } res = _findnext( lHandle, &tagData ); } // Close if we found any files if(lHandle != -1) _findclose(lHandle); } }
//----------------------------------------------------------------------- void FileSystemArchive::findFiles(const String& pattern, bool recursive, bool dirs, StringVector* simpleList, FileInfoList* detailList) const { long lHandle, res; struct _finddata_t tagData; // pattern can contain a directory name, separate it from mask size_t pos1 = pattern.rfind ('/'); size_t pos2 = pattern.rfind ('\\'); if (pos1 == pattern.npos || ((pos2 != pattern.npos) && (pos1 < pos2))) pos1 = pos2; String directory; if (pos1 != pattern.npos) directory = pattern.substr (0, pos1 + 1); String base_dir = mName; if (!directory.empty ()) { base_dir = concatenate_path(mName, directory); // Remove the last '/' base_dir.erase (base_dir.length () - 1); } //if there's a file with the name "norecurse" we shouldn't recurse further std::ifstream norecurseFile((base_dir + "/norecurse").c_str()); if (!norecurseFile.fail()) { return; } base_dir.append ("/*"); String full_pattern = concatenate_path(mName, pattern); lHandle = _findfirst(full_pattern.c_str(), &tagData); res = 0; while (lHandle != -1 && res != -1) { if ((dirs == ((tagData.attrib & _A_SUBDIR) != 0)) && (!dirs || !is_reserved_dir (tagData.name))) { if (simpleList) { simpleList->push_back(directory + tagData.name); } else if (detailList) { FileInfo fi; fi.archive = this; fi.filename = directory + tagData.name; fi.basename = tagData.name; fi.path = directory; 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) { // Remove directory name from pattern String mask ("/"); if (pos1 != pattern.npos) mask.append (pattern.substr (pos1 + 1)); else mask.append (pattern); lHandle = _findfirst(base_dir.c_str (), &tagData); res = 0; while (lHandle != -1 && res != -1) { //if the name of the directory is "source" we should ignore it, since these are directories //containing raw source materials (.psd files, .blend files etc) which we don't want to bring //into the client (they tend to be rather large) if ((tagData.attrib & _A_SUBDIR) && !is_reserved_dir (tagData.name) && !(tagData.attrib & _A_HIDDEN) && std::strcmp(tagData.name, "source") != 0) { // recurse base_dir = directory; base_dir.append (tagData.name).append (mask); findFiles(base_dir, recursive, dirs, simpleList, detailList); } res = _findnext( lHandle, &tagData ); } // Close if we found any files if(lHandle != -1) _findclose(lHandle); } }