1 // Copyright (C) 2002-2012 Nikolaus Gebhardt
\r
2 // This file is part of the "Irrlicht Engine".
\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
\r
5 #include "IrrCompileConfig.h"
\r
7 #include "CFileSystem.h"
\r
8 #include "IReadFile.h"
\r
9 #include "IWriteFile.h"
\r
10 #include "CZipReader.h"
\r
11 #include "CMountPointReader.h"
\r
12 #include "CPakReader.h"
\r
13 #include "CNPKReader.h"
\r
14 #include "CTarReader.h"
\r
15 #include "CWADReader.h"
\r
16 #include "CFileList.h"
\r
17 #include "CXMLReader.h"
\r
18 #include "CXMLWriter.h"
\r
21 #include "CAttributes.h"
\r
22 #include "CReadFile.h"
\r
23 #include "CMemoryFile.h"
\r
24 #include "CLimitReadFile.h"
\r
25 #include "CWriteFile.h"
\r
26 #include "irrList.h"
\r
28 #if defined (__STRICT_ANSI__)
\r
29 #error Compiling with __STRICT_ANSI__ not supported. g++ does set this when compiling with -std=c++11 or -std=c++0x. Use instead -std=gnu++11 or -std=gnu++0x. Or use -U__STRICT_ANSI__ to disable strict ansi.
\r
32 #if defined (_IRR_WINDOWS_API_)
\r
33 #if !defined ( _WIN32_WCE )
\r
34 #include <direct.h> // for _chdir
\r
35 #include <io.h> // for _access
\r
38 #elif (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_) || defined(_IRR_IOS_PLATFORM_) || defined(_IRR_ANDROID_PLATFORM_))
\r
43 #include <sys/types.h>
\r
45 #include <sys/stat.h>
\r
47 #elif defined(_IRR_EMSCRIPTEN_PLATFORM_)
\r
57 CFileSystem::CFileSystem()
\r
60 setDebugName("CFileSystem");
\r
63 setFileListSystem(FILESYSTEM_NATIVE);
\r
64 //! reset current working directory
\r
65 getWorkingDirectory();
\r
67 #ifdef __IRR_COMPILE_WITH_PAK_ARCHIVE_LOADER_
\r
68 ArchiveLoader.push_back(new CArchiveLoaderPAK(this));
\r
71 #ifdef __IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_
\r
72 ArchiveLoader.push_back(new CArchiveLoaderNPK(this));
\r
75 #ifdef __IRR_COMPILE_WITH_TAR_ARCHIVE_LOADER_
\r
76 ArchiveLoader.push_back(new CArchiveLoaderTAR(this));
\r
79 #ifdef __IRR_COMPILE_WITH_WAD_ARCHIVE_LOADER_
\r
80 ArchiveLoader.push_back(new CArchiveLoaderWAD(this));
\r
83 #ifdef __IRR_COMPILE_WITH_MOUNT_ARCHIVE_LOADER_
\r
84 ArchiveLoader.push_back(new CArchiveLoaderMount(this));
\r
87 #ifdef __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_
\r
88 ArchiveLoader.push_back(new CArchiveLoaderZIP(this));
\r
95 CFileSystem::~CFileSystem()
\r
99 for ( i=0; i < FileArchives.size(); ++i)
\r
101 FileArchives[i]->drop();
\r
104 for ( i=0; i < ArchiveLoader.size(); ++i)
\r
106 ArchiveLoader[i]->drop();
\r
111 //! opens a file for read access
\r
112 IReadFile* CFileSystem::createAndOpenFile(const io::path& filename)
\r
114 if ( filename.empty() )
\r
117 IReadFile* file = 0;
\r
120 for (i=0; i< FileArchives.size(); ++i)
\r
122 file = FileArchives[i]->createAndOpenFile(filename);
\r
127 // Create the file using an absolute path so that it matches
\r
128 // the scheme used by CNullDriver::getTexture().
\r
129 return CReadFile::createReadFile(getAbsolutePath(filename));
\r
133 //! Creates an IReadFile interface for treating memory like a file.
\r
134 IReadFile* CFileSystem::createMemoryReadFile(const void* memory, s32 len,
\r
135 const io::path& fileName, bool deleteMemoryWhenDropped)
\r
140 return new CMemoryReadFile(memory, len, fileName, deleteMemoryWhenDropped);
\r
144 //! Creates an IReadFile interface for reading files inside files
\r
145 IReadFile* CFileSystem::createLimitReadFile(const io::path& fileName,
\r
146 IReadFile* alreadyOpenedFile, long pos, long areaSize)
\r
148 if (!alreadyOpenedFile)
\r
151 return new CLimitReadFile(alreadyOpenedFile, pos, areaSize, fileName);
\r
155 //! Creates an IReadFile interface for treating memory like a file.
\r
156 IWriteFile* CFileSystem::createMemoryWriteFile(void* memory, s32 len,
\r
157 const io::path& fileName, bool deleteMemoryWhenDropped)
\r
162 return new CMemoryWriteFile(memory, len, fileName, deleteMemoryWhenDropped);
\r
166 //! Opens a file for write access.
\r
167 IWriteFile* CFileSystem::createAndWriteFile(const io::path& filename, bool append)
\r
169 return CWriteFile::createWriteFile(filename, append);
\r
173 //! Adds an external archive loader to the engine.
\r
174 void CFileSystem::addArchiveLoader(IArchiveLoader* loader)
\r
180 ArchiveLoader.push_back(loader);
\r
183 //! Returns the total number of archive loaders added.
\r
184 u32 CFileSystem::getArchiveLoaderCount() const
\r
186 return ArchiveLoader.size();
\r
189 //! Gets the archive loader by index.
\r
190 IArchiveLoader* CFileSystem::getArchiveLoader(u32 index) const
\r
192 if (index < ArchiveLoader.size())
\r
193 return ArchiveLoader[index];
\r
198 //! move the hirarchy of the filesystem. moves sourceIndex relative up or down
\r
199 bool CFileSystem::moveFileArchive(u32 sourceIndex, s32 relative)
\r
202 const s32 dest = (s32) sourceIndex + relative;
\r
203 const s32 dir = relative < 0 ? -1 : 1;
\r
204 const s32 sourceEnd = ((s32) FileArchives.size() ) - 1;
\r
207 for (s32 s = (s32) sourceIndex;s != dest; s += dir)
\r
209 if (s < 0 || s > sourceEnd || s + dir < 0 || s + dir > sourceEnd)
\r
212 t = FileArchives[s + dir];
\r
213 FileArchives[s + dir] = FileArchives[s];
\r
214 FileArchives[s] = t;
\r
221 //! Adds an archive to the file system.
\r
222 bool CFileSystem::addFileArchive(const io::path& filename, bool ignoreCase,
\r
223 bool ignorePaths, E_FILE_ARCHIVE_TYPE archiveType,
\r
224 const core::stringc& password,
\r
225 IFileArchive** retArchive)
\r
227 IFileArchive* archive = 0;
\r
230 // see if archive is already added
\r
231 if (changeArchivePassword(filename, password, retArchive))
\r
236 // do we know what type it should be?
\r
237 if (archiveType == EFAT_UNKNOWN || archiveType == EFAT_FOLDER)
\r
239 // try to load archive based on file name
\r
240 for (i = ArchiveLoader.size()-1; i >=0 ; --i)
\r
242 if (ArchiveLoader[i]->isALoadableFileFormat(filename))
\r
244 archive = ArchiveLoader[i]->createArchive(filename, ignoreCase, ignorePaths);
\r
250 // try to load archive based on content
\r
253 io::IReadFile* file = createAndOpenFile(filename);
\r
256 for (i = ArchiveLoader.size()-1; i >= 0; --i)
\r
259 if (ArchiveLoader[i]->isALoadableFileFormat(file))
\r
262 archive = ArchiveLoader[i]->createArchive(file, ignoreCase, ignorePaths);
\r
273 // try to open archive based on archive loader type
\r
275 io::IReadFile* file = 0;
\r
277 for (i = ArchiveLoader.size()-1; i >= 0; --i)
\r
279 if (ArchiveLoader[i]->isALoadableFileFormat(archiveType))
\r
281 // attempt to open file
\r
283 file = createAndOpenFile(filename);
\r
285 // is the file open?
\r
288 // attempt to open archive
\r
290 if (ArchiveLoader[i]->isALoadableFileFormat(file))
\r
293 archive = ArchiveLoader[i]->createArchive(file, ignoreCase, ignorePaths);
\r
300 // couldn't open file
\r
306 // if open, close the file
\r
313 FileArchives.push_back(archive);
\r
314 if (password.size())
\r
315 archive->Password=password;
\r
317 *retArchive = archive;
\r
322 os::Printer::log("Could not create archive for", filename, ELL_ERROR);
\r
329 bool CFileSystem::changeArchivePassword(const path& filename,
\r
330 const core::stringc& password,
\r
331 IFileArchive** archive)
\r
333 for (s32 idx = 0; idx < (s32)FileArchives.size(); ++idx)
\r
335 // TODO: This should go into a path normalization method
\r
336 // We need to check for directory names with trailing slash and without
\r
337 const path absPath = getAbsolutePath(filename);
\r
338 const path arcPath = FileArchives[idx]->getFileList()->getPath();
\r
339 if ((absPath == arcPath) || ((absPath+_IRR_TEXT("/")) == arcPath))
\r
341 if (password.size())
\r
342 FileArchives[idx]->Password=password;
\r
344 *archive = FileArchives[idx];
\r
352 bool CFileSystem::addFileArchive(IReadFile* file, bool ignoreCase,
\r
353 bool ignorePaths, E_FILE_ARCHIVE_TYPE archiveType,
\r
354 const core::stringc& password, IFileArchive** retArchive)
\r
356 if (!file || archiveType == EFAT_FOLDER)
\r
361 if (changeArchivePassword(file->getFileName(), password, retArchive))
\r
364 IFileArchive* archive = 0;
\r
367 if (archiveType == EFAT_UNKNOWN)
\r
369 // try to load archive based on file name
\r
370 for (i = ArchiveLoader.size()-1; i >=0 ; --i)
\r
372 if (ArchiveLoader[i]->isALoadableFileFormat(file->getFileName()))
\r
374 archive = ArchiveLoader[i]->createArchive(file, ignoreCase, ignorePaths);
\r
380 // try to load archive based on content
\r
383 for (i = ArchiveLoader.size()-1; i >= 0; --i)
\r
386 if (ArchiveLoader[i]->isALoadableFileFormat(file))
\r
389 archive = ArchiveLoader[i]->createArchive(file, ignoreCase, ignorePaths);
\r
398 // try to open archive based on archive loader type
\r
399 for (i = ArchiveLoader.size()-1; i >= 0; --i)
\r
401 if (ArchiveLoader[i]->isALoadableFileFormat(archiveType))
\r
403 // attempt to open archive
\r
405 if (ArchiveLoader[i]->isALoadableFileFormat(file))
\r
408 archive = ArchiveLoader[i]->createArchive(file, ignoreCase, ignorePaths);
\r
418 FileArchives.push_back(archive);
\r
419 if (password.size())
\r
420 archive->Password=password;
\r
422 *retArchive = archive;
\r
427 os::Printer::log("Could not create archive for", file->getFileName(), ELL_ERROR);
\r
435 //! Adds an archive to the file system.
\r
436 bool CFileSystem::addFileArchive(IFileArchive* archive)
\r
440 for (u32 i=0; i < FileArchives.size(); ++i)
\r
442 if (archive == FileArchives[i])
\r
447 FileArchives.push_back(archive);
\r
457 //! removes an archive from the file system.
\r
458 bool CFileSystem::removeFileArchive(u32 index)
\r
461 if (index < FileArchives.size())
\r
463 FileArchives[index]->drop();
\r
464 FileArchives.erase(index);
\r
471 //! removes an archive from the file system.
\r
472 bool CFileSystem::removeFileArchive(const io::path& filename)
\r
474 const path absPath = getAbsolutePath(filename);
\r
475 for (u32 i=0; i < FileArchives.size(); ++i)
\r
477 if (absPath == FileArchives[i]->getFileList()->getPath())
\r
478 return removeFileArchive(i);
\r
484 //! Removes an archive from the file system.
\r
485 bool CFileSystem::removeFileArchive(const IFileArchive* archive)
\r
487 for (u32 i=0; i < FileArchives.size(); ++i)
\r
489 if (archive == FileArchives[i])
\r
491 return removeFileArchive(i);
\r
498 //! gets an archive
\r
499 u32 CFileSystem::getFileArchiveCount() const
\r
501 return FileArchives.size();
\r
505 IFileArchive* CFileSystem::getFileArchive(u32 index)
\r
507 return index < getFileArchiveCount() ? FileArchives[index] : 0;
\r
511 //! Returns the string of the current working directory
\r
512 const io::path& CFileSystem::getWorkingDirectory()
\r
514 EFileSystemType type = FileSystemType;
\r
516 if (type != FILESYSTEM_NATIVE)
\r
518 type = FILESYSTEM_VIRTUAL;
\r
522 #if defined(_IRR_WINDOWS_API_)
\r
523 fschar_t tmp[_MAX_PATH];
\r
524 #if defined(_IRR_WCHAR_FILESYSTEM )
\r
525 _wgetcwd(tmp, _MAX_PATH);
\r
526 WorkingDirectory[FILESYSTEM_NATIVE] = tmp;
\r
527 WorkingDirectory[FILESYSTEM_NATIVE].replace(L'\\', L'/');
\r
529 _getcwd(tmp, _MAX_PATH);
\r
530 WorkingDirectory[FILESYSTEM_NATIVE] = tmp;
\r
531 WorkingDirectory[FILESYSTEM_NATIVE].replace('\\', '/');
\r
535 #if (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_))
\r
537 // getting the CWD is rather complex as we do not know the size
\r
538 // so try it until the call was successful
\r
539 // Note that neither the first nor the second parameter may be 0 according to POSIX
\r
541 #if defined(_IRR_WCHAR_FILESYSTEM )
\r
543 wchar_t *tmpPath = new wchar_t[pathSize];
\r
544 while ((pathSize < (1<<16)) && !(wgetcwd(tmpPath,pathSize)))
\r
548 tmpPath = new char[pathSize];
\r
552 WorkingDirectory[FILESYSTEM_NATIVE] = tmpPath;
\r
557 char *tmpPath = new char[pathSize];
\r
558 while ((pathSize < (1<<16)) && !(getcwd(tmpPath,pathSize)))
\r
562 tmpPath = new char[pathSize];
\r
566 WorkingDirectory[FILESYSTEM_NATIVE] = tmpPath;
\r
572 WorkingDirectory[type].validate();
\r
575 return WorkingDirectory[type];
\r
579 //! Changes the current Working Directory to the given string.
\r
580 bool CFileSystem::changeWorkingDirectoryTo(const io::path& newDirectory)
\r
582 bool success=false;
\r
584 if (FileSystemType != FILESYSTEM_NATIVE)
\r
586 WorkingDirectory[FILESYSTEM_VIRTUAL] = newDirectory;
\r
587 // is this empty string constant really intended?
\r
588 flattenFilename(WorkingDirectory[FILESYSTEM_VIRTUAL], _IRR_TEXT(""));
\r
593 WorkingDirectory[FILESYSTEM_NATIVE] = newDirectory;
\r
595 #if defined(_MSC_VER)
\r
596 #if defined(_IRR_WCHAR_FILESYSTEM)
\r
597 success = (_wchdir(newDirectory.c_str()) == 0);
\r
599 success = (_chdir(newDirectory.c_str()) == 0);
\r
602 #if defined(_IRR_WCHAR_FILESYSTEM)
\r
603 success = (_wchdir(newDirectory.c_str()) == 0);
\r
605 success = (chdir(newDirectory.c_str()) == 0);
\r
614 io::path CFileSystem::getAbsolutePath(const io::path& filename) const
\r
616 if ( filename.empty() )
\r
618 #if defined(_IRR_WINDOWS_API_)
\r
620 fschar_t fpath[_MAX_PATH];
\r
621 #if defined(_IRR_WCHAR_FILESYSTEM )
\r
622 p = _wfullpath(fpath, filename.c_str(), _MAX_PATH);
\r
623 core::stringw tmp(p);
\r
624 tmp.replace(L'\\', L'/');
\r
626 p = _fullpath(fpath, filename.c_str(), _MAX_PATH);
\r
627 core::stringc tmp(p);
\r
628 tmp.replace('\\', '/');
\r
631 #elif (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_))
\r
635 p = realpath(filename.c_str(), fpath);
\r
638 // content in fpath is unclear at this point
\r
639 if (!fpath[0]) // seems like fpath wasn't altered, use our best guess
\r
641 io::path tmp(filename);
\r
642 return flattenFilename(tmp);
\r
645 return io::path(fpath);
\r
647 if (filename[filename.size()-1]=='/')
\r
648 return io::path(p)+_IRR_TEXT("/");
\r
650 return io::path(p);
\r
652 return io::path(filename);
\r
657 //! returns the directory part of a filename, i.e. all until the first
\r
658 //! slash or backslash, excluding it. If no directory path is prefixed, a '.'
\r
660 io::path CFileSystem::getFileDir(const io::path& filename) const
\r
662 // find last forward or backslash
\r
663 s32 lastSlash = filename.findLast('/');
\r
664 const s32 lastBackSlash = filename.findLast('\\');
\r
665 lastSlash = lastSlash > lastBackSlash ? lastSlash : lastBackSlash;
\r
667 if ((u32)lastSlash < filename.size())
\r
668 return filename.subString(0, lastSlash);
\r
670 return _IRR_TEXT(".");
\r
674 //! returns the base part of a filename, i.e. all except for the directory
\r
675 //! part. If no directory path is prefixed, the full name is returned.
\r
676 io::path CFileSystem::getFileBasename(const io::path& filename, bool keepExtension) const
\r
678 // find last forward or backslash
\r
679 s32 lastSlash = filename.findLast('/');
\r
680 const s32 lastBackSlash = filename.findLast('\\');
\r
681 lastSlash = core::max_(lastSlash, lastBackSlash);
\r
683 // get number of chars after last dot
\r
685 if (!keepExtension)
\r
687 // take care to search only after last slash to check only for
\r
688 // dots in the filename
\r
689 end = filename.findLast('.');
\r
690 if (end == -1 || end < lastSlash)
\r
693 end = filename.size()-end;
\r
696 if ((u32)lastSlash < filename.size())
\r
697 return filename.subString(lastSlash+1, filename.size()-lastSlash-1-end);
\r
699 return filename.subString(0, filename.size()-end);
\r
705 //! flatten a path and file name for example: "/you/me/../." becomes "/you"
\r
706 io::path& CFileSystem::flattenFilename(io::path& directory, const io::path& root) const
\r
708 directory.replace('\\', '/');
\r
709 if (directory.lastChar() != '/')
\r
710 directory.append('/');
\r
717 bool lastWasRealDir=false;
\r
719 while ((pos = directory.findNext('/', lastpos)) >= 0)
\r
721 subdir = directory.subString(lastpos, pos - lastpos + 1);
\r
723 if (subdir == _IRR_TEXT("../"))
\r
725 if (lastWasRealDir)
\r
727 deletePathFromPath(dir, 2);
\r
728 lastWasRealDir=(dir.size()!=0);
\r
732 dir.append(subdir);
\r
733 lastWasRealDir=false;
\r
736 else if (subdir == _IRR_TEXT("/"))
\r
740 else if (subdir != _IRR_TEXT("./"))
\r
742 dir.append(subdir);
\r
743 lastWasRealDir=true;
\r
753 //! Get the relative filename, relative to the given directory
\r
754 path CFileSystem::getRelativeFilename(const path& filename, const path& directory) const
\r
756 if ( filename.empty() || directory.empty() )
\r
759 io::path path1, file, ext;
\r
760 core::splitFilename(getAbsolutePath(filename), &path1, &file, &ext);
\r
761 io::path path2(getAbsolutePath(directory));
\r
762 core::list<io::path> list1, list2;
\r
763 path1.split(list1, _IRR_TEXT("/\\"), 2);
\r
764 path2.split(list2, _IRR_TEXT("/\\"), 2);
\r
766 core::list<io::path>::ConstIterator it1,it2;
\r
770 #if defined (_IRR_WINDOWS_API_)
\r
771 fschar_t partition1 = 0, partition2 = 0;
\r
772 io::path prefix1, prefix2;
\r
773 if ( it1 != list1.end() )
\r
775 if ( it2 != list2.end() )
\r
777 if ( prefix1.size() > 1 && prefix1[1] == _IRR_TEXT(':') )
\r
778 partition1 = core::locale_lower(prefix1[0]);
\r
779 if ( prefix2.size() > 1 && prefix2[1] == _IRR_TEXT(':') )
\r
780 partition2 = core::locale_lower(prefix2[0]);
\r
782 // must have the same prefix or we can't resolve it to a relative filename
\r
783 if ( partition1 != partition2 )
\r
790 for (; i<list1.size() && i<list2.size()
\r
791 #if defined (_IRR_WINDOWS_API_)
\r
792 && (io::path(*it1).make_lower()==io::path(*it2).make_lower())
\r
801 path1=_IRR_TEXT("");
\r
802 for (; i<list2.size(); ++i)
\r
803 path1 += _IRR_TEXT("../");
\r
804 while (it1 != list1.end())
\r
807 path1 += _IRR_TEXT('/');
\r
812 path1 += _IRR_TEXT('.');
\r
819 //! Sets the current file systen type
\r
820 EFileSystemType CFileSystem::setFileListSystem(EFileSystemType listType)
\r
822 EFileSystemType current = FileSystemType;
\r
823 FileSystemType = listType;
\r
828 //! Creates a list of files and directories in the current working directory
\r
829 IFileList* CFileSystem::createFileList()
\r
832 io::path Path = getWorkingDirectory();
\r
833 Path.replace('\\', '/');
\r
834 if (!Path.empty() && Path.lastChar() != '/')
\r
837 //! Construct from native filesystem
\r
838 if (FileSystemType == FILESYSTEM_NATIVE)
\r
840 // --------------------------------------------
\r
841 //! Windows version
\r
842 #ifdef _IRR_WINDOWS_API_
\r
843 #if !defined ( _WIN32_WCE )
\r
845 r = new CFileList(Path, true, false);
\r
847 // TODO: Should be unified once mingw adapts the proper types
\r
848 #if defined(__GNUC__)
\r
849 long hFile; //mingw return type declaration
\r
854 struct _tfinddata_t c_file;
\r
855 if( (hFile = _tfindfirst( _T("*"), &c_file )) != -1L )
\r
859 r->addItem(Path + c_file.name, 0, c_file.size, (_A_SUBDIR & c_file.attrib) != 0, 0);
\r
861 while( _tfindnext( hFile, &c_file ) == 0 );
\r
863 _findclose( hFile );
\r
868 //entry.Name = "E:\\";
\r
869 //entry.isDirectory = true;
\r
870 //Files.push_back(entry);
\r
873 // --------------------------------------------
\r
875 #if (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_))
\r
878 r = new CFileList(Path, false, false);
\r
880 r->addItem(Path + _IRR_TEXT(".."), 0, 0, true, 0);
\r
882 //! We use the POSIX compliant methods instead of scandir
\r
883 DIR* dirHandle=opendir(Path.c_str());
\r
886 struct dirent *dirEntry;
\r
887 while ((dirEntry=readdir(dirHandle)))
\r
890 bool isDirectory = false;
\r
892 if((strcmp(dirEntry->d_name, ".")==0) ||
\r
893 (strcmp(dirEntry->d_name, "..")==0))
\r
898 if (stat(dirEntry->d_name, &buf)==0)
\r
900 size = buf.st_size;
\r
901 isDirectory = S_ISDIR(buf.st_mode);
\r
903 #if !defined(_IRR_SOLARIS_PLATFORM_) && !defined(__CYGWIN__)
\r
904 // only available on some systems
\r
907 isDirectory = dirEntry->d_type == DT_DIR;
\r
911 r->addItem(Path + dirEntry->d_name, 0, size, isDirectory, 0);
\r
913 closedir(dirHandle);
\r
919 //! create file list for the virtual filesystem
\r
920 r = new CFileList(Path, false, false);
\r
922 //! add relative navigation
\r
927 r->addItem(Path + _IRR_TEXT("."), 0, 0, true, 0);
\r
930 r->addItem(Path + _IRR_TEXT(".."), 0, 0, true, 0);
\r
933 for (u32 i=0; i < FileArchives.size(); ++i)
\r
935 const IFileList *merge = FileArchives[i]->getFileList();
\r
937 for (u32 j=0; j < merge->getFileCount(); ++j)
\r
939 if (core::isInSameDirectory(Path, merge->getFullFileName(j)) == 0)
\r
941 r->addItem(merge->getFullFileName(j), merge->getFileOffset(j), merge->getFileSize(j), merge->isDirectory(j), 0);
\r
952 //! Creates an empty filelist
\r
953 IFileList* CFileSystem::createEmptyFileList(const io::path& path, bool ignoreCase, bool ignorePaths)
\r
955 return new CFileList(path, ignoreCase, ignorePaths);
\r
959 //! determines if a file exists and would be able to be opened.
\r
960 bool CFileSystem::existFile(const io::path& filename) const
\r
962 for (u32 i=0; i < FileArchives.size(); ++i)
\r
963 if (FileArchives[i]->getFileList()->findFile(filename)!=-1)
\r
966 #if defined(_MSC_VER)
\r
967 #if defined(_IRR_WCHAR_FILESYSTEM)
\r
968 return (_waccess(filename.c_str(), 0) != -1);
\r
970 return (_access(filename.c_str(), 0) != -1);
\r
972 #elif defined(F_OK)
\r
973 #if defined(_IRR_WCHAR_FILESYSTEM)
\r
974 return (_waccess(filename.c_str(), F_OK) != -1);
\r
976 return (access(filename.c_str(), F_OK) != -1);
\r
979 return (access(filename.c_str(), 0) != -1);
\r
984 //! Creates a XML Reader from a file.
\r
985 IXMLReader* CFileSystem::createXMLReader(const io::path& filename)
\r
987 #ifdef _IRR_COMPILE_WITH_XML_
\r
988 IReadFile* file = createAndOpenFile(filename);
\r
992 IXMLReader* reader = createXMLReader(file);
\r
1002 //! Creates a XML Reader from a file.
\r
1003 IXMLReader* CFileSystem::createXMLReader(IReadFile* file)
\r
1005 #ifdef _IRR_COMPILE_WITH_XML_
\r
1009 return createIXMLReader(file);
\r
1017 //! Creates a XML Reader from a file.
\r
1018 IXMLReaderUTF8* CFileSystem::createXMLReaderUTF8(const io::path& filename)
\r
1020 #ifdef _IRR_COMPILE_WITH_XML_
\r
1021 IReadFile* file = createAndOpenFile(filename);
\r
1025 IXMLReaderUTF8* reader = createIXMLReaderUTF8(file);
\r
1035 //! Creates a XML Reader from a file.
\r
1036 IXMLReaderUTF8* CFileSystem::createXMLReaderUTF8(IReadFile* file)
\r
1038 #ifdef _IRR_COMPILE_WITH_XML_
\r
1042 return createIXMLReaderUTF8(file);
\r
1050 //! Creates a XML Writer from a file.
\r
1051 IXMLWriter* CFileSystem::createXMLWriter(const io::path& filename)
\r
1053 #ifdef _IRR_COMPILE_WITH_XML_
\r
1054 IWriteFile* file = createAndWriteFile(filename);
\r
1055 IXMLWriter* writer = 0;
\r
1058 writer = createXMLWriter(file);
\r
1069 //! Creates a XML Writer from a file.
\r
1070 IXMLWriter* CFileSystem::createXMLWriter(IWriteFile* file)
\r
1072 #ifdef _IRR_COMPILE_WITH_XML_
\r
1073 return createIXMLWriter(file);
\r
1080 //! Creates a XML Writer from a file.
\r
1081 IXMLWriterUTF8* CFileSystem::createXMLWriterUTF8(const io::path& filename)
\r
1083 #ifdef _IRR_COMPILE_WITH_XML_
\r
1084 IWriteFile* file = createAndWriteFile(filename);
\r
1085 IXMLWriterUTF8* writer = 0;
\r
1088 writer = createXMLWriterUTF8(file);
\r
1099 //! Creates a XML Writer from a file.
\r
1100 IXMLWriterUTF8* CFileSystem::createXMLWriterUTF8(IWriteFile* file)
\r
1102 #ifdef _IRR_COMPILE_WITH_XML_
\r
1103 return createIXMLWriterUTF8(file);
\r
1111 //! creates a filesystem which is able to open files from the ordinary file system,
\r
1112 //! and out of zipfiles, which are able to be added to the filesystem.
\r
1113 IFileSystem* createFileSystem()
\r
1115 return new CFileSystem();
\r
1119 //! Creates a new empty collection of attributes, usable for serialization and more.
\r
1120 IAttributes* CFileSystem::createEmptyAttributes(video::IVideoDriver* driver)
\r
1122 return new CAttributes(driver);
\r
1126 } // end namespace irr
\r
1127 } // end namespace io
\r