Project

General

Profile

SO3Engine
SO3ScolFileSystem.cpp
Go to the documentation of this file.
1/*
2-----------------------------------------------------------------------------
3This source file is part of OpenSpace3D
4For the latest info, see http://www.openspace3d.com
5
6Copyright (c) 2012 I-maginer
7
8This program is free software; you can redistribute it and/or modify it under
9the terms of the GNU Lesser General Public License as published by the Free Software
10Foundation; either version 2 of the License, or (at your option) any later
11version.
12
13This program is distributed in the hope that it will be useful, but WITHOUT
14ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
16
17You should have received a copy of the GNU Lesser General Public License along with
18this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19Place - Suite 330, Boston, MA 02111-1307, USA, or go to
20http://www.gnu.org/copyleft/lesser.txt
21
22-----------------------------------------------------------------------------
23*/
24
29#include <scolPlugin.h>
31
32//TODO use boost file system
33#ifdef _WIN32
34 #include <io.h>
35#else
36 #include "OgreSearchOps.h"
37 #include <sys/param.h>
38 #include <sys/stat.h>
39 #define MAX_PATH MAXPATHLEN
40#endif
41
42#include <boost/filesystem.hpp>
43
44namespace SO3
45{
46#ifdef ANDROID
47static std::map< Ogre::String, std::vector< Ogre::String > > mApkFiles;
48
49static bool IsFolderParsed(Ogre::String Folder)
50{
51 bool parsed = false;
52 //force lowercase
53 Ogre::StringUtil::toLowerCase(Folder);
54 boost::filesystem::path filedir(Folder);
55 if (filedir.has_filename())
56 filedir = filedir.parent_path();
57
58 std::map< Ogre::String, std::vector< Ogre::String > >::iterator iter = mApkFiles.find(filedir.generic_string());
59 if (iter != mApkFiles.end())
60 parsed = true;
61 //else
62 //Ogre::LogManager::getSingleton().getDefaultLog()->logMessage("[DEBUG] ::IsFolderParsed not parser yet : " + Folder);
63
64 return parsed;
65}
66
67static void ParseFolder(AAssetManager* AssetMgr, Ogre::String Folder)
68{
69 std::vector<Ogre::String> mFilenames;
70 //force lowercase
71 Ogre::StringUtil::toLowerCase(Folder);
72 boost::filesystem::path filedir(Folder);
73 if (filedir.has_filename())
74 filedir = filedir.parent_path();
75
76 //Ogre::LogManager::getSingleton().getDefaultLog()->logMessage("[DEBUG] ::ParseFolder : " + filedir.generic_string());
77 AAssetDir* dir = AAssetManager_openDir(AssetMgr, filedir.generic_string().c_str());
78 const char* fileName = NULL;
79 while ((fileName = AAssetDir_getNextFileName(dir)) != NULL)
80 {
81 //force lowercase
82 Ogre::String fname(fileName);
83 Ogre::StringUtil::toLowerCase(fname);
84 mFilenames.push_back(fname);
85 //Ogre::LogManager::getSingleton().getDefaultLog()->logMessage("[DEBUG] ::ParseFolder : " + fname);
86 }
87
88 mApkFiles.insert(std::make_pair(filedir.generic_string(), mFilenames));
89 AAssetDir_close(dir);
90}
91#endif
92
94
95//-----------------------------------------------------------------------
96SO3ScolFileSystemArchive::SO3ScolFileSystemArchive(const Ogre::String& name, const Ogre::String& archType, bool readOnly)
97: Ogre::Archive(name, archType)
98{
99 // Even failed attempt to write to read only location violates Apple AppStore validation process.
100 // And successful writing to some probe file does not prove that whole location with subfolders
101 // is writable. Therefore we accept read only flag from outside and do not try to be too smart.
102 mReadOnly = readOnly;
103
104#ifdef ANDROID
105 mAssetManager = 0;
106 mApk = false;
107
108 if (mName.size() > 0 && mName[0] == '/')
109 mName.erase(mName.begin());
110
111 if ((mName.compare(0, 4, "apk/") == 0) || (mName.compare(0, 4, "APK/") == 0))
112 {
113 mReadOnly = true;
114 mName = mName.substr(4);
115 mPathPreFix = mName;
116
117 struct android_app* androidApp = (struct android_app*)SCgetExtra("this_inst");
118 if (androidApp != NULL)
119 {
120 mAssetManager = androidApp->activity->assetManager;
121 }
122 mApk = true;
123 }
124
125 /*
126 if (mApk && !IsFolderParsed(mName))
127 {
128 struct android_app* androidApp = (struct android_app*)SCgetExtra("this_inst");
129 if (androidApp != NULL)
130 {
131 ParseFolder(mAssetManager, mName);
132 }
133 }*/
134#endif
135}
136
137//-----------------------------------------------------------------------
139{
140#ifdef _WIN32
141 return false;
142#else
143 return true;
144#endif
145}
146
147//-----------------------------------------------------------------------
148#ifdef ANDROID
150{
151 return mApk;
152}
153#endif
154
155//-----------------------------------------------------------------------
157{
158 return (fn[0] == '.' && (fn[1] == 0 || (fn[1] == '.' && fn[2] == 0)));
159}
160
161//-----------------------------------------------------------------------
162boost::filesystem::path SO3ScolFileSystemArchive::concatenate_path(const Ogre::String base, const Ogre::String name)
163{
164 boost::filesystem::path out = base;
165 if (base.empty() || boost::filesystem::path(name).is_absolute())
166 out = name;
167 else
168 out /= name;
169
170 return out;
171}
172
173//-----------------------------------------------------------------------
174void SO3ScolFileSystemArchive::findFiles(const Ogre::String& pattern, bool recursive,
175 bool dirs, Ogre::StringVector* simpleList, Ogre::FileInfoList* detailList) const
176{
177 intptr_t lHandle, res;
178 struct _finddata_t tagData;
179
180 // pattern can contain a directory name, separate it from mask
181 size_t pos1 = pattern.rfind('/');
182 size_t pos2 = pattern.rfind('\\');
183 if (pos1 == pattern.npos || ((pos2 != pattern.npos) && (pos1 < pos2)))
184 pos1 = pos2;
185 Ogre::String directory;
186 if (pos1 != pattern.npos)
187 directory = pattern.substr(0, pos1 + 1);
188
189 boost::filesystem::path full_pattern = concatenate_path(mName, pattern);
190
191 lHandle = _findfirst(full_pattern.generic_string().c_str(), &tagData);
192 res = 0;
193 while (lHandle != -1 && res != -1)
194 {
195 if ((dirs == ((tagData.attrib & _A_SUBDIR) != 0)) &&
196 (!msIgnoreHidden || (tagData.attrib & _A_HIDDEN) == 0) &&
197 (!dirs || !is_reserved_dir(tagData.name)))
198 {
199 if (simpleList)
200 {
201 simpleList->push_back(directory + tagData.name);
202 }
203 else if (detailList)
204 {
205 Ogre::FileInfo fi;
206 fi.archive = this;
207 fi.filename = directory + tagData.name;
208 fi.basename = tagData.name;
209 fi.path = directory;
210 fi.compressedSize = tagData.size;
211 fi.uncompressedSize = tagData.size;
212 detailList->push_back(fi);
213 }
214 }
215 res = _findnext(lHandle, &tagData);
216 }
217 // Close if we found any files
218 if (lHandle != -1)
219 _findclose(lHandle);
220
221 // Now find directories
222 if (recursive)
223 {
224 boost::filesystem::path base_dir = mName;
225 if (!directory.empty())
226 {
227 base_dir = concatenate_path(mName, directory);
228 }
229 base_dir /= "*";
230
231 // Remove directory name from pattern
232 Ogre::String mask("/");
233 if (pos1 != pattern.npos)
234 mask.append(pattern.substr(pos1 + 1));
235 else
236 mask.append(pattern);
237
238 lHandle = _findfirst(base_dir.generic_string().c_str(), &tagData);
239 res = 0;
240 while (lHandle != -1 && res != -1)
241 {
242 if ((tagData.attrib & _A_SUBDIR) &&
243 (!msIgnoreHidden || (tagData.attrib & _A_HIDDEN) == 0) &&
244 !is_reserved_dir(tagData.name))
245 {
246 // recurse
247 base_dir = directory;
248 base_dir /= tagData.name;
249 base_dir.append(mask);
250
251 findFiles(base_dir.generic_string(), recursive, dirs, simpleList, detailList);
252 }
253 res = _findnext(lHandle, &tagData);
254 }
255 // Close if we found any files
256 if (lHandle != -1)
257 _findclose(lHandle);
258 }
259}
260
261//-----------------------------------------------------------------------
263{
264#ifdef ANDROID
265 mApkFiles.clear();
266#endif
267
268 unload();
269}
270
271//-----------------------------------------------------------------------
273{
274 // nothing to do here
275}
276
277//-----------------------------------------------------------------------
279{
280 // nothing to see here, move along
281}
282
283//-----------------------------------------------------------------------
284Ogre::DataStreamPtr SO3ScolFileSystemArchive::open(const Ogre::String& filename, bool readOnly) const
285{
286 MMechostr(MSKDEBUG, ">>> Open archive : %s\n", filename.c_str());
287#ifdef ANDROID
288 if (isApk())
289 {
290 Ogre::String fname = filename;
291
292 if ((fname.compare(0, 4, "apk/") == 0) || (fname.compare(0, 4, "APK/") == 0))
293 fname = fname.substr(4);
294 else
295 fname = mPathPreFix + fname;
296
297 Ogre::DataStreamPtr stream;
298 AAsset* asset = AAssetManager_open(mAssetManager, fname.c_str(), AASSET_MODE_BUFFER);
299 //try lowercase
300 if (!asset)
301 {
302 Ogre::StringUtil::toLowerCase(fname);
303 asset = AAssetManager_open(mAssetManager, fname.c_str(), AASSET_MODE_UNKNOWN);
304 }
305
306 if (asset)
307 {
308 off_t length = AAsset_getLength(asset);
309 void* membuf = OGRE_MALLOC(length, Ogre::MEMCATEGORY_GENERAL);
310 memcpy(membuf, AAsset_getBuffer(asset), length);
311 AAsset_close(asset);
312
313 stream = Ogre::DataStreamPtr(new Ogre::MemoryDataStream(membuf, length, true, true));
314 }
315 return stream;
316 }
317#endif
318
319 boost::filesystem::path full_path = concatenate_path(mName, filename);
320 try
321 {
322 if (!boost::filesystem::exists(full_path))
323 {
324 //try lowercase
325 if (isCaseSensitive())
326 {
327 Ogre::String lfilename = filename;
328 Ogre::StringUtil::toLowerCase(lfilename);
329 full_path = concatenate_path(mName, lfilename);
330 if (!boost::filesystem::exists(full_path))
331 {
332 OGRE_EXCEPT(Ogre::Exception::ERR_FILE_NOT_FOUND,
333 "Cannot open file: " + filename,
334 "SO3ScolFileSystemArchive::open");
335 }
336 }
337 else
338 {
339 OGRE_EXCEPT(Ogre::Exception::ERR_FILE_NOT_FOUND,
340 "Cannot open file: " + filename,
341 "SO3ScolFileSystemArchive::open");
342 }
343 }
344 }
345 catch (std::exception &)
346 {
347 OGRE_EXCEPT(Ogre::Exception::ERR_FILE_NOT_FOUND,
348 "Cannot open file: " + filename,
349 "SO3ScolFileSystemArchive::open");
350 }
351
352 // Use filesystem to determine size
353 // (quicker than streaming to the end and back)
354 struct stat tagStat;
355 int ret = stat(full_path.generic_string().c_str(), &tagStat);
356 assert(ret == 0 && "Problem getting file size");
357 (void)ret; // Silence warning
358
359 // Always open in binary mode
360 // Also, always include reading
361 std::ios::openmode mode = std::ios::in | std::ios::binary;
362 std::istream* baseStream = 0;
363 std::ifstream* roStream = 0;
364 std::fstream* rwStream = 0;
365
366 if (!readOnly && isReadOnly())
367 {
368 OGRE_EXCEPT(Ogre::Exception::ERR_INVALIDPARAMS,
369 "Cannot open a file in read-write mode in a read-only archive",
370 "SO3ScolFileSystemArchive::open");
371 }
372
373 if (!readOnly)
374 {
375 mode |= std::ios::out;
376 rwStream = OGRE_NEW_T(std::fstream, Ogre::MEMCATEGORY_GENERAL)();
377 rwStream->open(full_path.c_str(), mode);
378 baseStream = rwStream;
379 }
380 else
381 {
382 roStream = OGRE_NEW_T(std::ifstream, Ogre::MEMCATEGORY_GENERAL)();
383 roStream->open(full_path.c_str(), mode);
384 baseStream = roStream;
385 }
386
387
388 // Should check ensure open succeeded, in case fail for some reason.
389 if (baseStream->fail())
390 {
391 OGRE_DELETE_T(roStream, basic_ifstream, Ogre::MEMCATEGORY_GENERAL);
392 OGRE_DELETE_T(rwStream, basic_fstream, Ogre::MEMCATEGORY_GENERAL);
393 OGRE_EXCEPT(Ogre::Exception::ERR_FILE_NOT_FOUND,
394 "Cannot open file: " + filename,
395 "SO3ScolFileSystemArchive::open");
396 }
397
399 Ogre::FileStreamDataStream* stream = 0;
400 if (rwStream)
401 {
402 // use the writeable stream
403 stream = OGRE_NEW Ogre::FileStreamDataStream(filename,
404 rwStream, (size_t)tagStat.st_size, true);
405 }
406 else
407 {
408 // read-only stream
409 stream = OGRE_NEW Ogre::FileStreamDataStream(filename,
410 roStream, (size_t)tagStat.st_size, true);
411 }
412 return Ogre::DataStreamPtr(stream);
413}
414
415//---------------------------------------------------------------------
416Ogre::DataStreamPtr SO3ScolFileSystemArchive::create(const Ogre::String& filename)
417{
418 if (isReadOnly())
419 {
420 OGRE_EXCEPT(Ogre::Exception::ERR_INVALIDPARAMS,
421 "Cannot create a file in a read-only archive",
422 "SO3ScolFileSystemArchive::remove");
423 }
424
425 boost::filesystem::path full_path = concatenate_path(mName, filename);
426
427 // Always open in binary mode
428 // Also, always include reading
429 std::ios::openmode mode = std::ios::out | std::ios::binary;
430 std::fstream* rwStream = OGRE_NEW_T(std::fstream, Ogre::MEMCATEGORY_GENERAL)();
431 rwStream->open(full_path.c_str(), mode);
432
433 // Should check ensure open succeeded, in case fail for some reason.
434 if (rwStream->fail())
435 {
436 OGRE_DELETE_T(rwStream, basic_fstream, Ogre::MEMCATEGORY_GENERAL);
437 OGRE_EXCEPT(Ogre::Exception::ERR_FILE_NOT_FOUND,
438 "Cannot open file: " + filename,
439 "SO3ScolFileSystemArchive::create");
440 }
441
443 Ogre::FileStreamDataStream* stream = OGRE_NEW Ogre::FileStreamDataStream(filename,
444 rwStream, 0, true);
445
446 return Ogre::DataStreamPtr(stream);
447}
448
449//---------------------------------------------------------------------
450void SO3ScolFileSystemArchive::remove(const Ogre::String& filename)
451{
452 if (isReadOnly())
453 {
454 OGRE_EXCEPT(Ogre::Exception::ERR_INVALIDPARAMS,
455 "Cannot remove a file from a read-only archive",
456 "SO3ScolFileSystemArchive::remove");
457 }
458
459 boost::filesystem::path full_path = concatenate_path(mName, filename);
460 try
461 {
462 if (!boost::filesystem::exists(full_path))
463 {
464 //try lowercase
465 if (isCaseSensitive())
466 {
467 Ogre::String lfilename = filename;
468 Ogre::StringUtil::toLowerCase(lfilename);
469 full_path = concatenate_path(mName, lfilename);
470 if (!boost::filesystem::exists(full_path))
471 {
472 OGRE_EXCEPT(Ogre::Exception::ERR_FILE_NOT_FOUND,
473 "Cannot open file: " + filename,
474 "SO3ScolFileSystemArchive::remove");
475 }
476 }
477 else
478 {
479 OGRE_EXCEPT(Ogre::Exception::ERR_FILE_NOT_FOUND,
480 "Cannot open file: " + filename,
481 "SO3ScolFileSystemArchive::remove");
482 }
483 }
484 }
485 catch (std::exception&)
486 {
487 OGRE_EXCEPT(Ogre::Exception::ERR_FILE_NOT_FOUND,
488 "Cannot open file: " + filename,
489 "SO3ScolFileSystemArchive::remove");
490 }
491
492 ::remove(full_path.generic_string().c_str());
493}
494
495//-----------------------------------------------------------------------
496Ogre::StringVectorPtr SO3ScolFileSystemArchive::list(bool recursive, bool dirs) const
497{
498#ifdef ANDROID
499 if (isApk())
500 {
501 if (!IsFolderParsed(mName))
502 ParseFolder(mAssetManager, mName);
503
504 Ogre::StringVectorPtr files(new Ogre::StringVector);
505 boost::filesystem::path filedir(mName);
506 if (filedir.has_filename())
507 filedir = filedir.parent_path();
508
509 //force lowercase
510 Ogre::String fdir(filedir.generic_string().c_str());
511 Ogre::StringUtil::toLowerCase(fdir);
512
513 std::map<Ogre::String, std::vector< Ogre::String > >::iterator iter = mApkFiles.find(fdir);
514 std::vector< Ogre::String > fileList = iter->second;
515 for (size_t i = 0; i < fileList.size(); i++)
516 {
517 files->push_back(fileList[i]);
518 }
519 return files;
520 }
521#endif
522
523 // directory change requires locking due to saved returns
524 auto ret = std::make_shared<Ogre::StringVector>();
525 findFiles("*", recursive, dirs, ret.get(), 0);
526
527 return ret;
528}
529
530//-----------------------------------------------------------------------
531Ogre::FileInfoListPtr SO3ScolFileSystemArchive::listFileInfo(bool recursive, bool dirs) const
532{
533#ifdef ANDROID
534 if (isApk())
535 {
536 if (!IsFolderParsed(mName))
537 ParseFolder(mAssetManager, mName);
538
539 Ogre::FileInfoListPtr files(new Ogre::FileInfoList);
540 boost::filesystem::path filedir(mName);
541 if (filedir.has_filename())
542 filedir = filedir.parent_path();
543
544 //force lowercase
545 Ogre::String fdir(filedir.generic_string().c_str());
546 Ogre::StringUtil::toLowerCase(fdir);
547
548 std::map<Ogre::String, std::vector< Ogre::String > >::iterator iter = mApkFiles.find(fdir);
549 std::vector< Ogre::String > fileList = iter->second;
550 for (size_t i = 0; i < fileList.size(); i++)
551 {
552 AAsset* asset = AAssetManager_open(mAssetManager, (mPathPreFix + fileList[i]).c_str(), AASSET_MODE_UNKNOWN);
553
554 //try lowercase
555 if (!asset)
556 {
557 Ogre::String lowername = mPathPreFix + fileList[i];
558 Ogre::StringUtil::toLowerCase(lowername);
559 asset = AAssetManager_open(mAssetManager, lowername.c_str(), AASSET_MODE_UNKNOWN);
560 }
561
562 if (asset)
563 {
564 Ogre::FileInfo info;
565 info.archive = this;
566 info.filename = fileList[i];
567 info.path = mName;
568 info.basename = fileList[i];
569 info.compressedSize = AAsset_getLength(asset);
570 info.uncompressedSize = info.compressedSize;
571 files->push_back(info);
572 AAsset_close(asset);
573 }
574 }
575 return files;
576 }
577#endif
578
579 auto ret = std::make_shared<Ogre::FileInfoList>();
580 findFiles("*", recursive, dirs, 0, ret.get());
581
582 return ret;
583}
584
585//-----------------------------------------------------------------------
586Ogre::StringVectorPtr SO3ScolFileSystemArchive::find(const Ogre::String& pattern, bool recursive, bool dirs) const
587{
588#ifdef ANDROID
589 if (isApk())
590 {
591 auto ret = std::make_shared<Ogre::StringVector>();
592 Ogre::String fname = pattern;
593
594 if ((fname.compare(0, 4, "apk/") == 0) || (fname.compare(0, 4, "APK/") == 0))
595 fname = fname.substr(4);
596 else
597 fname = mPathPreFix + fname;
598
599 AAsset* asset = AAssetManager_open(mAssetManager, fname.c_str(), AASSET_MODE_UNKNOWN);
600 //try lowercase
601 if (!asset)
602 {
603 Ogre::StringUtil::toLowerCase(fname);
604 asset = AAssetManager_open(mAssetManager, fname.c_str(), AASSET_MODE_UNKNOWN);
605 }
606 if (asset)
607 {
608 ret->push_back(pattern);
609 AAsset_close(asset);
610 }
611
612 if (ret->empty())
613 Ogre::LogManager::getSingleton().getDefaultLog()->logMessage("[WARNING] ::find Could not find the files in APK with pattern : " + pattern);
614 return ret;
615 }
616#endif
617
618 auto ret = std::make_shared<Ogre::StringVector>();
619 findFiles(pattern, recursive, dirs, ret.get(), 0);
620
621 //retry lowercase
622 if (isCaseSensitive() && ret->empty())
623 {
624 Ogre::String lpattern = pattern;
625 Ogre::StringUtil::toLowerCase(lpattern);
626 findFiles(lpattern, recursive, dirs, ret.get(), 0);
627 }
628 return ret;
629}
630
631//-----------------------------------------------------------------------
632Ogre::FileInfoListPtr SO3ScolFileSystemArchive::findFileInfo(const Ogre::String& pattern, bool recursive, bool dirs) const
633{
634#ifdef ANDROID
635 if (isApk())
636 {
637 auto ret = std::make_shared<Ogre::FileInfoList>();
638 Ogre::String fname = pattern;
639
640 if ((fname.compare(0, 4, "apk/") == 0) || (fname.compare(0, 4, "APK/") == 0))
641 fname = fname.substr(4);
642 else
643 fname = mPathPreFix + fname;
644
645 AAsset* asset = AAssetManager_open(mAssetManager, fname.c_str(), AASSET_MODE_UNKNOWN);
646 //try lowercase
647 if (!asset)
648 {
649 Ogre::StringUtil::toLowerCase(fname);
650 asset = AAssetManager_open(mAssetManager, fname.c_str(), AASSET_MODE_UNKNOWN);
651 }
652 if (asset)
653 {
654 Ogre::FileInfo info;
655 info.archive = this;
656 info.filename = pattern;
657 info.path = mName;
658 info.basename = pattern;
659 info.compressedSize = AAsset_getLength(asset);
660 info.uncompressedSize = info.compressedSize;
661 ret->push_back(info);
662 AAsset_close(asset);
663 }
664
665 if (ret->empty())
666 Ogre::LogManager::getSingleton().getDefaultLog()->logMessage("[WARNING] ::findFileInfo Could not find the files in APK with pattern : " + pattern);
667 return ret;
668 }
669#endif
670
671 auto ret = std::make_shared<Ogre::FileInfoList>();
672 findFiles(pattern, recursive, dirs, 0, ret.get());
673
674 //retry lowercase
675 if (isCaseSensitive() && ret->empty())
676 {
677 Ogre::String lpattern = pattern;
678 Ogre::StringUtil::toLowerCase(lpattern);
679 findFiles(lpattern, recursive, dirs, 0, ret.get());
680 }
681 return ret;
682}
683
684//-----------------------------------------------------------------------
685bool SO3ScolFileSystemArchive::exists(const Ogre::String& filename) const
686{
687#ifdef ANDROID
688 if (isApk())
689 {
690 Ogre::String fname = filename;
691
692 if ((fname.compare(0, 4, "apk/") == 0) || (fname.compare(0, 4, "APK/") == 0))
693 fname = fname.substr(4);
694 else
695 fname = mPathPreFix + fname;
696
697 AAsset* asset = AAssetManager_open(mAssetManager, fname.c_str(), AASSET_MODE_UNKNOWN);
698 //try lowercase
699 if (!asset)
700 {
701 Ogre::StringUtil::toLowerCase(fname);
702 asset = AAssetManager_open(mAssetManager, fname.c_str(), AASSET_MODE_UNKNOWN);
703 }
704 if (asset)
705 {
706 AAsset_close(asset);
707 //MMechostr(MSKDEBUG, ">>> Found path : from %s > %s", mPathPreFix.c_str(), fname.c_str());
708 return true;
709 }
710 return false;
711 }
712#endif
713
714 boost::filesystem::path full_path = concatenate_path(mName, filename);
715 try
716 {
717 if (boost::filesystem::exists(full_path))
718 {
719 return true;
720 }
721 else
722 {
723 //try lowercase
724 if (isCaseSensitive())
725 {
726 Ogre::String lfilename = filename;
727 Ogre::StringUtil::toLowerCase(lfilename);
728 full_path = concatenate_path(mName, lfilename);
729 if (boost::filesystem::exists(full_path))
730 {
731 return true;
732 }
733 }
734 else
735 return false;
736 }
737 }
738 catch (std::exception&)
739 {
740 return false;
741 }
742
743/*
744#ifdef ANDROID
745 if (ret)
746 MMechostr(MSKDEBUG, ">>> Found path : from %s > %s", mPathPreFix.c_str(), full_path.c_str());
747#endif
748*/
749
750 return false;
751}
752
753//---------------------------------------------------------------------
754time_t SO3ScolFileSystemArchive::getModifiedTime(const Ogre::String& filename) const
755{
756#ifdef ANDROID
757 if (isApk())
758 return 0;
759#endif
760
761 boost::filesystem::path full_path = concatenate_path(mName, filename);
762 try
763 {
764 if (!boost::filesystem::exists(full_path))
765 {
766 //try lowercase
767 if (isCaseSensitive())
768 {
769 Ogre::String lfilename = filename;
770 Ogre::StringUtil::toLowerCase(lfilename);
771 full_path = concatenate_path(mName, lfilename);
772 if (!boost::filesystem::exists(full_path))
773 {
774 return 0;
775 }
776 }
777 else
778 return 0;
779 }
780 }
781 catch (std::exception&)
782 {
783 return 0;
784 }
785
786 struct stat tagStat;
787 bool ret = (stat(full_path.generic_string().c_str(), &tagStat) == 0);
788
789 if (ret)
790 {
791 return tagStat.st_mtime;
792 }
793 else
794 {
795 return 0;
796 }
797}
798
799//-----------------------------------------------------------------------
800const Ogre::String& SO3ScolFileSystemArchiveFactory::getType(void) const
801{
802 static Ogre::String name = "ScolFileSystem";
803 return name;
804}
805
806}
MMechostr(MSKDEBUG, " > Start loading Plugin SO3Engine dll\n")
const Ogre::String & getType(void) const
virtual bool isCaseSensitive(void) const
virtual time_t getModifiedTime(const Ogre::String &filename) const
void findFiles(const Ogre::String &pattern, bool recursive, bool dirs, Ogre::StringVector *simpleList, Ogre::FileInfoList *detailList) const
static boost::filesystem::path concatenate_path(const Ogre::String base, const Ogre::String name)
virtual Ogre::StringVectorPtr list(bool recursive=true, bool dirs=false) const
virtual void remove(const Ogre::String &filename)
virtual Ogre::FileInfoListPtr findFileInfo(const Ogre::String &pattern, bool recursive=true, bool dirs=false) const
static bool is_reserved_dir(const char *fn)
virtual Ogre::DataStreamPtr open(const Ogre::String &filename, bool readOnly=true) const
SO3ScolFileSystemArchive(const Ogre::String &name, const Ogre::String &archType, bool readOnly)
virtual Ogre::FileInfoListPtr listFileInfo(bool recursive=true, bool dirs=false) const
virtual Ogre::DataStreamPtr create(const Ogre::String &filename)
virtual Ogre::StringVectorPtr find(const Ogre::String &pattern, bool recursive=true, bool dirs=false) const
virtual bool exists(const Ogre::String &filename) const