aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/irrlicht-1.8/source/Irrlicht/CFileSystem.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/irrlicht-1.8/source/Irrlicht/CFileSystem.cpp')
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/CFileSystem.cpp2156
1 files changed, 1078 insertions, 1078 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CFileSystem.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CFileSystem.cpp
index 0358480..134a469 100644
--- a/libraries/irrlicht-1.8/source/Irrlicht/CFileSystem.cpp
+++ b/libraries/irrlicht-1.8/source/Irrlicht/CFileSystem.cpp
@@ -1,1078 +1,1078 @@
1// Copyright (C) 2002-2012 Nikolaus Gebhardt 1// Copyright (C) 2002-2012 Nikolaus Gebhardt
2// This file is part of the "Irrlicht Engine". 2// This file is part of the "Irrlicht Engine".
3// For conditions of distribution and use, see copyright notice in irrlicht.h 3// For conditions of distribution and use, see copyright notice in irrlicht.h
4 4
5#include "IrrCompileConfig.h" 5#include "IrrCompileConfig.h"
6 6
7#include "CFileSystem.h" 7#include "CFileSystem.h"
8#include "IReadFile.h" 8#include "IReadFile.h"
9#include "IWriteFile.h" 9#include "IWriteFile.h"
10#include "CZipReader.h" 10#include "CZipReader.h"
11#include "CMountPointReader.h" 11#include "CMountPointReader.h"
12#include "CPakReader.h" 12#include "CPakReader.h"
13#include "CNPKReader.h" 13#include "CNPKReader.h"
14#include "CTarReader.h" 14#include "CTarReader.h"
15#include "CWADReader.h" 15#include "CWADReader.h"
16#include "CFileList.h" 16#include "CFileList.h"
17#include "CXMLReader.h" 17#include "CXMLReader.h"
18#include "CXMLWriter.h" 18#include "CXMLWriter.h"
19#include "stdio.h" 19#include "stdio.h"
20#include "os.h" 20#include "os.h"
21#include "CAttributes.h" 21#include "CAttributes.h"
22#include "CMemoryFile.h" 22#include "CMemoryFile.h"
23#include "CLimitReadFile.h" 23#include "CLimitReadFile.h"
24#include "irrList.h" 24#include "irrList.h"
25 25
26#if defined (_IRR_WINDOWS_API_) 26#if defined (_IRR_WINDOWS_API_)
27 #if !defined ( _WIN32_WCE ) 27 #if !defined ( _WIN32_WCE )
28 #include <direct.h> // for _chdir 28 #include <direct.h> // for _chdir
29 #include <io.h> // for _access 29 #include <io.h> // for _access
30 #include <tchar.h> 30 #include <tchar.h>
31 #endif 31 #endif
32#else 32#else
33 #if (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_)) 33 #if (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_))
34 #include <stdio.h> 34 #include <stdio.h>
35 #include <stdlib.h> 35 #include <stdlib.h>
36 #include <string.h> 36 #include <string.h>
37 #include <limits.h> 37 #include <limits.h>
38 #include <sys/types.h> 38 #include <sys/types.h>
39 #include <dirent.h> 39 #include <dirent.h>
40 #include <sys/stat.h> 40 #include <sys/stat.h>
41 #include <unistd.h> 41 #include <unistd.h>
42 #endif 42 #endif
43#endif 43#endif
44 44
45namespace irr 45namespace irr
46{ 46{
47namespace io 47namespace io
48{ 48{
49 49
50//! constructor 50//! constructor
51CFileSystem::CFileSystem() 51CFileSystem::CFileSystem()
52{ 52{
53 #ifdef _DEBUG 53 #ifdef _DEBUG
54 setDebugName("CFileSystem"); 54 setDebugName("CFileSystem");
55 #endif 55 #endif
56 56
57 setFileListSystem(FILESYSTEM_NATIVE); 57 setFileListSystem(FILESYSTEM_NATIVE);
58 //! reset current working directory 58 //! reset current working directory
59 getWorkingDirectory(); 59 getWorkingDirectory();
60 60
61#ifdef __IRR_COMPILE_WITH_PAK_ARCHIVE_LOADER_ 61#ifdef __IRR_COMPILE_WITH_PAK_ARCHIVE_LOADER_
62 ArchiveLoader.push_back(new CArchiveLoaderPAK(this)); 62 ArchiveLoader.push_back(new CArchiveLoaderPAK(this));
63#endif 63#endif
64 64
65#ifdef __IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_ 65#ifdef __IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_
66 ArchiveLoader.push_back(new CArchiveLoaderNPK(this)); 66 ArchiveLoader.push_back(new CArchiveLoaderNPK(this));
67#endif 67#endif
68 68
69#ifdef __IRR_COMPILE_WITH_TAR_ARCHIVE_LOADER_ 69#ifdef __IRR_COMPILE_WITH_TAR_ARCHIVE_LOADER_
70 ArchiveLoader.push_back(new CArchiveLoaderTAR(this)); 70 ArchiveLoader.push_back(new CArchiveLoaderTAR(this));
71#endif 71#endif
72 72
73#ifdef __IRR_COMPILE_WITH_WAD_ARCHIVE_LOADER_ 73#ifdef __IRR_COMPILE_WITH_WAD_ARCHIVE_LOADER_
74 ArchiveLoader.push_back(new CArchiveLoaderWAD(this)); 74 ArchiveLoader.push_back(new CArchiveLoaderWAD(this));
75#endif 75#endif
76 76
77#ifdef __IRR_COMPILE_WITH_MOUNT_ARCHIVE_LOADER_ 77#ifdef __IRR_COMPILE_WITH_MOUNT_ARCHIVE_LOADER_
78 ArchiveLoader.push_back(new CArchiveLoaderMount(this)); 78 ArchiveLoader.push_back(new CArchiveLoaderMount(this));
79#endif 79#endif
80 80
81#ifdef __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ 81#ifdef __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_
82 ArchiveLoader.push_back(new CArchiveLoaderZIP(this)); 82 ArchiveLoader.push_back(new CArchiveLoaderZIP(this));
83#endif 83#endif
84 84
85} 85}
86 86
87 87
88//! destructor 88//! destructor
89CFileSystem::~CFileSystem() 89CFileSystem::~CFileSystem()
90{ 90{
91 u32 i; 91 u32 i;
92 92
93 for ( i=0; i < FileArchives.size(); ++i) 93 for ( i=0; i < FileArchives.size(); ++i)
94 { 94 {
95 FileArchives[i]->drop(); 95 FileArchives[i]->drop();
96 } 96 }
97 97
98 for ( i=0; i < ArchiveLoader.size(); ++i) 98 for ( i=0; i < ArchiveLoader.size(); ++i)
99 { 99 {
100 ArchiveLoader[i]->drop(); 100 ArchiveLoader[i]->drop();
101 } 101 }
102} 102}
103 103
104 104
105//! opens a file for read access 105//! opens a file for read access
106IReadFile* CFileSystem::createAndOpenFile(const io::path& filename) 106IReadFile* CFileSystem::createAndOpenFile(const io::path& filename)
107{ 107{
108 IReadFile* file = 0; 108 IReadFile* file = 0;
109 u32 i; 109 u32 i;
110 110
111 for (i=0; i< FileArchives.size(); ++i) 111 for (i=0; i< FileArchives.size(); ++i)
112 { 112 {
113 file = FileArchives[i]->createAndOpenFile(filename); 113 file = FileArchives[i]->createAndOpenFile(filename);
114 if (file) 114 if (file)
115 return file; 115 return file;
116 } 116 }
117 117
118 // Create the file using an absolute path so that it matches 118 // Create the file using an absolute path so that it matches
119 // the scheme used by CNullDriver::getTexture(). 119 // the scheme used by CNullDriver::getTexture().
120 return createReadFile(getAbsolutePath(filename)); 120 return createReadFile(getAbsolutePath(filename));
121} 121}
122 122
123 123
124//! Creates an IReadFile interface for treating memory like a file. 124//! Creates an IReadFile interface for treating memory like a file.
125IReadFile* CFileSystem::createMemoryReadFile(void* memory, s32 len, 125IReadFile* CFileSystem::createMemoryReadFile(void* memory, s32 len,
126 const io::path& fileName, bool deleteMemoryWhenDropped) 126 const io::path& fileName, bool deleteMemoryWhenDropped)
127{ 127{
128 if (!memory) 128 if (!memory)
129 return 0; 129 return 0;
130 else 130 else
131 return new CMemoryFile(memory, len, fileName, deleteMemoryWhenDropped); 131 return new CMemoryFile(memory, len, fileName, deleteMemoryWhenDropped);
132 } 132 }
133 133
134 134
135//! Creates an IReadFile interface for reading files inside files 135//! Creates an IReadFile interface for reading files inside files
136IReadFile* CFileSystem::createLimitReadFile(const io::path& fileName, 136IReadFile* CFileSystem::createLimitReadFile(const io::path& fileName,
137 IReadFile* alreadyOpenedFile, long pos, long areaSize) 137 IReadFile* alreadyOpenedFile, long pos, long areaSize)
138{ 138{
139 if (!alreadyOpenedFile) 139 if (!alreadyOpenedFile)
140 return 0; 140 return 0;
141 else 141 else
142 return new CLimitReadFile(alreadyOpenedFile, pos, areaSize, fileName); 142 return new CLimitReadFile(alreadyOpenedFile, pos, areaSize, fileName);
143} 143}
144 144
145 145
146//! Creates an IReadFile interface for treating memory like a file. 146//! Creates an IReadFile interface for treating memory like a file.
147IWriteFile* CFileSystem::createMemoryWriteFile(void* memory, s32 len, 147IWriteFile* CFileSystem::createMemoryWriteFile(void* memory, s32 len,
148 const io::path& fileName, bool deleteMemoryWhenDropped) 148 const io::path& fileName, bool deleteMemoryWhenDropped)
149{ 149{
150 if (!memory) 150 if (!memory)
151 return 0; 151 return 0;
152 else 152 else
153 return new CMemoryFile(memory, len, fileName, deleteMemoryWhenDropped); 153 return new CMemoryFile(memory, len, fileName, deleteMemoryWhenDropped);
154} 154}
155 155
156 156
157//! Opens a file for write access. 157//! Opens a file for write access.
158IWriteFile* CFileSystem::createAndWriteFile(const io::path& filename, bool append) 158IWriteFile* CFileSystem::createAndWriteFile(const io::path& filename, bool append)
159{ 159{
160 return createWriteFile(filename, append); 160 return createWriteFile(filename, append);
161} 161}
162 162
163 163
164//! Adds an external archive loader to the engine. 164//! Adds an external archive loader to the engine.
165void CFileSystem::addArchiveLoader(IArchiveLoader* loader) 165void CFileSystem::addArchiveLoader(IArchiveLoader* loader)
166{ 166{
167 if (!loader) 167 if (!loader)
168 return; 168 return;
169 169
170 loader->grab(); 170 loader->grab();
171 ArchiveLoader.push_back(loader); 171 ArchiveLoader.push_back(loader);
172} 172}
173 173
174//! Returns the total number of archive loaders added. 174//! Returns the total number of archive loaders added.
175u32 CFileSystem::getArchiveLoaderCount() const 175u32 CFileSystem::getArchiveLoaderCount() const
176{ 176{
177 return ArchiveLoader.size(); 177 return ArchiveLoader.size();
178} 178}
179 179
180//! Gets the archive loader by index. 180//! Gets the archive loader by index.
181IArchiveLoader* CFileSystem::getArchiveLoader(u32 index) const 181IArchiveLoader* CFileSystem::getArchiveLoader(u32 index) const
182{ 182{
183 if (index < ArchiveLoader.size()) 183 if (index < ArchiveLoader.size())
184 return ArchiveLoader[index]; 184 return ArchiveLoader[index];
185 else 185 else
186 return 0; 186 return 0;
187} 187}
188 188
189//! move the hirarchy of the filesystem. moves sourceIndex relative up or down 189//! move the hirarchy of the filesystem. moves sourceIndex relative up or down
190bool CFileSystem::moveFileArchive(u32 sourceIndex, s32 relative) 190bool CFileSystem::moveFileArchive(u32 sourceIndex, s32 relative)
191{ 191{
192 bool r = false; 192 bool r = false;
193 const s32 dest = (s32) sourceIndex + relative; 193 const s32 dest = (s32) sourceIndex + relative;
194 const s32 dir = relative < 0 ? -1 : 1; 194 const s32 dir = relative < 0 ? -1 : 1;
195 const s32 sourceEnd = ((s32) FileArchives.size() ) - 1; 195 const s32 sourceEnd = ((s32) FileArchives.size() ) - 1;
196 IFileArchive *t; 196 IFileArchive *t;
197 197
198 for (s32 s = (s32) sourceIndex;s != dest; s += dir) 198 for (s32 s = (s32) sourceIndex;s != dest; s += dir)
199 { 199 {
200 if (s < 0 || s > sourceEnd || s + dir < 0 || s + dir > sourceEnd) 200 if (s < 0 || s > sourceEnd || s + dir < 0 || s + dir > sourceEnd)
201 continue; 201 continue;
202 202
203 t = FileArchives[s + dir]; 203 t = FileArchives[s + dir];
204 FileArchives[s + dir] = FileArchives[s]; 204 FileArchives[s + dir] = FileArchives[s];
205 FileArchives[s] = t; 205 FileArchives[s] = t;
206 r = true; 206 r = true;
207 } 207 }
208 return r; 208 return r;
209} 209}
210 210
211 211
212//! Adds an archive to the file system. 212//! Adds an archive to the file system.
213bool CFileSystem::addFileArchive(const io::path& filename, bool ignoreCase, 213bool CFileSystem::addFileArchive(const io::path& filename, bool ignoreCase,
214 bool ignorePaths, E_FILE_ARCHIVE_TYPE archiveType, 214 bool ignorePaths, E_FILE_ARCHIVE_TYPE archiveType,
215 const core::stringc& password, 215 const core::stringc& password,
216 IFileArchive** retArchive) 216 IFileArchive** retArchive)
217{ 217{
218 IFileArchive* archive = 0; 218 IFileArchive* archive = 0;
219 bool ret = false; 219 bool ret = false;
220 220
221 // see if archive is already added 221 // see if archive is already added
222 if (changeArchivePassword(filename, password, retArchive)) 222 if (changeArchivePassword(filename, password, retArchive))
223 return true; 223 return true;
224 224
225 s32 i; 225 s32 i;
226 226
227 // do we know what type it should be? 227 // do we know what type it should be?
228 if (archiveType == EFAT_UNKNOWN || archiveType == EFAT_FOLDER) 228 if (archiveType == EFAT_UNKNOWN || archiveType == EFAT_FOLDER)
229 { 229 {
230 // try to load archive based on file name 230 // try to load archive based on file name
231 for (i = ArchiveLoader.size()-1; i >=0 ; --i) 231 for (i = ArchiveLoader.size()-1; i >=0 ; --i)
232 { 232 {
233 if (ArchiveLoader[i]->isALoadableFileFormat(filename)) 233 if (ArchiveLoader[i]->isALoadableFileFormat(filename))
234 { 234 {
235 archive = ArchiveLoader[i]->createArchive(filename, ignoreCase, ignorePaths); 235 archive = ArchiveLoader[i]->createArchive(filename, ignoreCase, ignorePaths);
236 if (archive) 236 if (archive)
237 break; 237 break;
238 } 238 }
239 } 239 }
240 240
241 // try to load archive based on content 241 // try to load archive based on content
242 if (!archive) 242 if (!archive)
243 { 243 {
244 io::IReadFile* file = createAndOpenFile(filename); 244 io::IReadFile* file = createAndOpenFile(filename);
245 if (file) 245 if (file)
246 { 246 {
247 for (i = ArchiveLoader.size()-1; i >= 0; --i) 247 for (i = ArchiveLoader.size()-1; i >= 0; --i)
248 { 248 {
249 file->seek(0); 249 file->seek(0);
250 if (ArchiveLoader[i]->isALoadableFileFormat(file)) 250 if (ArchiveLoader[i]->isALoadableFileFormat(file))
251 { 251 {
252 file->seek(0); 252 file->seek(0);
253 archive = ArchiveLoader[i]->createArchive(file, ignoreCase, ignorePaths); 253 archive = ArchiveLoader[i]->createArchive(file, ignoreCase, ignorePaths);
254 if (archive) 254 if (archive)
255 break; 255 break;
256 } 256 }
257 } 257 }
258 file->drop(); 258 file->drop();
259 } 259 }
260 } 260 }
261 } 261 }
262 else 262 else
263 { 263 {
264 // try to open archive based on archive loader type 264 // try to open archive based on archive loader type
265 265
266 io::IReadFile* file = 0; 266 io::IReadFile* file = 0;
267 267
268 for (i = ArchiveLoader.size()-1; i >= 0; --i) 268 for (i = ArchiveLoader.size()-1; i >= 0; --i)
269 { 269 {
270 if (ArchiveLoader[i]->isALoadableFileFormat(archiveType)) 270 if (ArchiveLoader[i]->isALoadableFileFormat(archiveType))
271 { 271 {
272 // attempt to open file 272 // attempt to open file
273 if (!file) 273 if (!file)
274 file = createAndOpenFile(filename); 274 file = createAndOpenFile(filename);
275 275
276 // is the file open? 276 // is the file open?
277 if (file) 277 if (file)
278 { 278 {
279 // attempt to open archive 279 // attempt to open archive
280 file->seek(0); 280 file->seek(0);
281 if (ArchiveLoader[i]->isALoadableFileFormat(file)) 281 if (ArchiveLoader[i]->isALoadableFileFormat(file))
282 { 282 {
283 file->seek(0); 283 file->seek(0);
284 archive = ArchiveLoader[i]->createArchive(file, ignoreCase, ignorePaths); 284 archive = ArchiveLoader[i]->createArchive(file, ignoreCase, ignorePaths);
285 if (archive) 285 if (archive)
286 break; 286 break;
287 } 287 }
288 } 288 }
289 else 289 else
290 { 290 {
291 // couldn't open file 291 // couldn't open file
292 break; 292 break;
293 } 293 }
294 } 294 }
295 } 295 }
296 296
297 // if open, close the file 297 // if open, close the file
298 if (file) 298 if (file)
299 file->drop(); 299 file->drop();
300 } 300 }
301 301
302 if (archive) 302 if (archive)
303 { 303 {
304 FileArchives.push_back(archive); 304 FileArchives.push_back(archive);
305 if (password.size()) 305 if (password.size())
306 archive->Password=password; 306 archive->Password=password;
307 if (retArchive) 307 if (retArchive)
308 *retArchive = archive; 308 *retArchive = archive;
309 ret = true; 309 ret = true;
310 } 310 }
311 else 311 else
312 { 312 {
313 os::Printer::log("Could not create archive for", filename, ELL_ERROR); 313 os::Printer::log("Could not create archive for", filename, ELL_ERROR);
314 } 314 }
315 315
316 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; 316 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
317 return ret; 317 return ret;
318} 318}
319 319
320// don't expose! 320// don't expose!
321bool CFileSystem::changeArchivePassword(const path& filename, 321bool CFileSystem::changeArchivePassword(const path& filename,
322 const core::stringc& password, 322 const core::stringc& password,
323 IFileArchive** archive) 323 IFileArchive** archive)
324{ 324{
325 for (s32 idx = 0; idx < (s32)FileArchives.size(); ++idx) 325 for (s32 idx = 0; idx < (s32)FileArchives.size(); ++idx)
326 { 326 {
327 // TODO: This should go into a path normalization method 327 // TODO: This should go into a path normalization method
328 // We need to check for directory names with trailing slash and without 328 // We need to check for directory names with trailing slash and without
329 const path absPath = getAbsolutePath(filename); 329 const path absPath = getAbsolutePath(filename);
330 const path arcPath = FileArchives[idx]->getFileList()->getPath(); 330 const path arcPath = FileArchives[idx]->getFileList()->getPath();
331 if ((absPath == arcPath) || ((absPath+_IRR_TEXT("/")) == arcPath)) 331 if ((absPath == arcPath) || ((absPath+_IRR_TEXT("/")) == arcPath))
332 { 332 {
333 if (password.size()) 333 if (password.size())
334 FileArchives[idx]->Password=password; 334 FileArchives[idx]->Password=password;
335 if (archive) 335 if (archive)
336 *archive = FileArchives[idx]; 336 *archive = FileArchives[idx];
337 return true; 337 return true;
338 } 338 }
339 } 339 }
340 340
341 return false; 341 return false;
342} 342}
343 343
344bool CFileSystem::addFileArchive(IReadFile* file, bool ignoreCase, 344bool CFileSystem::addFileArchive(IReadFile* file, bool ignoreCase,
345 bool ignorePaths, E_FILE_ARCHIVE_TYPE archiveType, 345 bool ignorePaths, E_FILE_ARCHIVE_TYPE archiveType,
346 const core::stringc& password, IFileArchive** retArchive) 346 const core::stringc& password, IFileArchive** retArchive)
347{ 347{
348 if (!file || archiveType == EFAT_FOLDER) 348 if (!file || archiveType == EFAT_FOLDER)
349 return false; 349 return false;
350 350
351 if (file) 351 if (file)
352 { 352 {
353 if (changeArchivePassword(file->getFileName(), password, retArchive)) 353 if (changeArchivePassword(file->getFileName(), password, retArchive))
354 return true; 354 return true;
355 355
356 IFileArchive* archive = 0; 356 IFileArchive* archive = 0;
357 s32 i; 357 s32 i;
358 358
359 if (archiveType == EFAT_UNKNOWN) 359 if (archiveType == EFAT_UNKNOWN)
360 { 360 {
361 // try to load archive based on file name 361 // try to load archive based on file name
362 for (i = ArchiveLoader.size()-1; i >=0 ; --i) 362 for (i = ArchiveLoader.size()-1; i >=0 ; --i)
363 { 363 {
364 if (ArchiveLoader[i]->isALoadableFileFormat(file->getFileName())) 364 if (ArchiveLoader[i]->isALoadableFileFormat(file->getFileName()))
365 { 365 {
366 archive = ArchiveLoader[i]->createArchive(file, ignoreCase, ignorePaths); 366 archive = ArchiveLoader[i]->createArchive(file, ignoreCase, ignorePaths);
367 if (archive) 367 if (archive)
368 break; 368 break;
369 } 369 }
370 } 370 }
371 371
372 // try to load archive based on content 372 // try to load archive based on content
373 if (!archive) 373 if (!archive)
374 { 374 {
375 for (i = ArchiveLoader.size()-1; i >= 0; --i) 375 for (i = ArchiveLoader.size()-1; i >= 0; --i)
376 { 376 {
377 file->seek(0); 377 file->seek(0);
378 if (ArchiveLoader[i]->isALoadableFileFormat(file)) 378 if (ArchiveLoader[i]->isALoadableFileFormat(file))
379 { 379 {
380 file->seek(0); 380 file->seek(0);
381 archive = ArchiveLoader[i]->createArchive(file, ignoreCase, ignorePaths); 381 archive = ArchiveLoader[i]->createArchive(file, ignoreCase, ignorePaths);
382 if (archive) 382 if (archive)
383 break; 383 break;
384 } 384 }
385 } 385 }
386 } 386 }
387 } 387 }
388 else 388 else
389 { 389 {
390 // try to open archive based on archive loader type 390 // try to open archive based on archive loader type
391 for (i = ArchiveLoader.size()-1; i >= 0; --i) 391 for (i = ArchiveLoader.size()-1; i >= 0; --i)
392 { 392 {
393 if (ArchiveLoader[i]->isALoadableFileFormat(archiveType)) 393 if (ArchiveLoader[i]->isALoadableFileFormat(archiveType))
394 { 394 {
395 // attempt to open archive 395 // attempt to open archive
396 file->seek(0); 396 file->seek(0);
397 if (ArchiveLoader[i]->isALoadableFileFormat(file)) 397 if (ArchiveLoader[i]->isALoadableFileFormat(file))
398 { 398 {
399 file->seek(0); 399 file->seek(0);
400 archive = ArchiveLoader[i]->createArchive(file, ignoreCase, ignorePaths); 400 archive = ArchiveLoader[i]->createArchive(file, ignoreCase, ignorePaths);
401 if (archive) 401 if (archive)
402 break; 402 break;
403 } 403 }
404 } 404 }
405 } 405 }
406 } 406 }
407 407
408 if (archive) 408 if (archive)
409 { 409 {
410 FileArchives.push_back(archive); 410 FileArchives.push_back(archive);
411 if (password.size()) 411 if (password.size())
412 archive->Password=password; 412 archive->Password=password;
413 if (retArchive) 413 if (retArchive)
414 *retArchive = archive; 414 *retArchive = archive;
415 return true; 415 return true;
416 } 416 }
417 else 417 else
418 { 418 {
419 os::Printer::log("Could not create archive for", file->getFileName(), ELL_ERROR); 419 os::Printer::log("Could not create archive for", file->getFileName(), ELL_ERROR);
420 } 420 }
421 } 421 }
422 422
423 return false; 423 return false;
424} 424}
425 425
426 426
427//! Adds an archive to the file system. 427//! Adds an archive to the file system.
428bool CFileSystem::addFileArchive(IFileArchive* archive) 428bool CFileSystem::addFileArchive(IFileArchive* archive)
429{ 429{
430 for (u32 i=0; i < FileArchives.size(); ++i) 430 for (u32 i=0; i < FileArchives.size(); ++i)
431 { 431 {
432 if (archive == FileArchives[i]) 432 if (archive == FileArchives[i])
433 { 433 {
434 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; 434 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
435 return false; 435 return false;
436 } 436 }
437 } 437 }
438 FileArchives.push_back(archive); 438 FileArchives.push_back(archive);
439 return true; 439 return true;
440} 440}
441 441
442 442
443//! removes an archive from the file system. 443//! removes an archive from the file system.
444bool CFileSystem::removeFileArchive(u32 index) 444bool CFileSystem::removeFileArchive(u32 index)
445{ 445{
446 bool ret = false; 446 bool ret = false;
447 if (index < FileArchives.size()) 447 if (index < FileArchives.size())
448 { 448 {
449 FileArchives[index]->drop(); 449 FileArchives[index]->drop();
450 FileArchives.erase(index); 450 FileArchives.erase(index);
451 ret = true; 451 ret = true;
452 } 452 }
453 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; 453 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
454 return ret; 454 return ret;
455} 455}
456 456
457 457
458//! removes an archive from the file system. 458//! removes an archive from the file system.
459bool CFileSystem::removeFileArchive(const io::path& filename) 459bool CFileSystem::removeFileArchive(const io::path& filename)
460{ 460{
461 const path absPath = getAbsolutePath(filename); 461 const path absPath = getAbsolutePath(filename);
462 for (u32 i=0; i < FileArchives.size(); ++i) 462 for (u32 i=0; i < FileArchives.size(); ++i)
463 { 463 {
464 if (absPath == FileArchives[i]->getFileList()->getPath()) 464 if (absPath == FileArchives[i]->getFileList()->getPath())
465 return removeFileArchive(i); 465 return removeFileArchive(i);
466 } 466 }
467 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; 467 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
468 return false; 468 return false;
469} 469}
470 470
471 471
472//! Removes an archive from the file system. 472//! Removes an archive from the file system.
473bool CFileSystem::removeFileArchive(const IFileArchive* archive) 473bool CFileSystem::removeFileArchive(const IFileArchive* archive)
474{ 474{
475 for (u32 i=0; i < FileArchives.size(); ++i) 475 for (u32 i=0; i < FileArchives.size(); ++i)
476 { 476 {
477 if (archive == FileArchives[i]) 477 if (archive == FileArchives[i])
478 { 478 {
479 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; 479 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
480 return removeFileArchive(i); 480 return removeFileArchive(i);
481 } 481 }
482 } 482 }
483 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; 483 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
484 return false; 484 return false;
485} 485}
486 486
487 487
488//! gets an archive 488//! gets an archive
489u32 CFileSystem::getFileArchiveCount() const 489u32 CFileSystem::getFileArchiveCount() const
490{ 490{
491 return FileArchives.size(); 491 return FileArchives.size();
492} 492}
493 493
494 494
495IFileArchive* CFileSystem::getFileArchive(u32 index) 495IFileArchive* CFileSystem::getFileArchive(u32 index)
496{ 496{
497 return index < getFileArchiveCount() ? FileArchives[index] : 0; 497 return index < getFileArchiveCount() ? FileArchives[index] : 0;
498} 498}
499 499
500 500
501//! Returns the string of the current working directory 501//! Returns the string of the current working directory
502const io::path& CFileSystem::getWorkingDirectory() 502const io::path& CFileSystem::getWorkingDirectory()
503{ 503{
504 EFileSystemType type = FileSystemType; 504 EFileSystemType type = FileSystemType;
505 505
506 if (type != FILESYSTEM_NATIVE) 506 if (type != FILESYSTEM_NATIVE)
507 { 507 {
508 type = FILESYSTEM_VIRTUAL; 508 type = FILESYSTEM_VIRTUAL;
509 } 509 }
510 else 510 else
511 { 511 {
512 #if defined(_IRR_WINDOWS_CE_PLATFORM_) 512 #if defined(_IRR_WINDOWS_CE_PLATFORM_)
513 // does not need this 513 // does not need this
514 #elif defined(_IRR_WINDOWS_API_) 514 #elif defined(_IRR_WINDOWS_API_)
515 fschar_t tmp[_MAX_PATH]; 515 fschar_t tmp[_MAX_PATH];
516 #if defined(_IRR_WCHAR_FILESYSTEM ) 516 #if defined(_IRR_WCHAR_FILESYSTEM )
517 _wgetcwd(tmp, _MAX_PATH); 517 _wgetcwd(tmp, _MAX_PATH);
518 WorkingDirectory[FILESYSTEM_NATIVE] = tmp; 518 WorkingDirectory[FILESYSTEM_NATIVE] = tmp;
519 WorkingDirectory[FILESYSTEM_NATIVE].replace(L'\\', L'/'); 519 WorkingDirectory[FILESYSTEM_NATIVE].replace(L'\\', L'/');
520 #else 520 #else
521 _getcwd(tmp, _MAX_PATH); 521 _getcwd(tmp, _MAX_PATH);
522 WorkingDirectory[FILESYSTEM_NATIVE] = tmp; 522 WorkingDirectory[FILESYSTEM_NATIVE] = tmp;
523 WorkingDirectory[FILESYSTEM_NATIVE].replace('\\', '/'); 523 WorkingDirectory[FILESYSTEM_NATIVE].replace('\\', '/');
524 #endif 524 #endif
525 #endif 525 #endif
526 526
527 #if (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_)) 527 #if (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_))
528 528
529 // getting the CWD is rather complex as we do not know the size 529 // getting the CWD is rather complex as we do not know the size
530 // so try it until the call was successful 530 // so try it until the call was successful
531 // Note that neither the first nor the second parameter may be 0 according to POSIX 531 // Note that neither the first nor the second parameter may be 0 according to POSIX
532 532
533 #if defined(_IRR_WCHAR_FILESYSTEM ) 533 #if defined(_IRR_WCHAR_FILESYSTEM )
534 u32 pathSize=256; 534 u32 pathSize=256;
535 wchar_t *tmpPath = new wchar_t[pathSize]; 535 wchar_t *tmpPath = new wchar_t[pathSize];
536 while ((pathSize < (1<<16)) && !(wgetcwd(tmpPath,pathSize))) 536 while ((pathSize < (1<<16)) && !(wgetcwd(tmpPath,pathSize)))
537 { 537 {
538 delete [] tmpPath; 538 delete [] tmpPath;
539 pathSize *= 2; 539 pathSize *= 2;
540 tmpPath = new char[pathSize]; 540 tmpPath = new char[pathSize];
541 } 541 }
542 if (tmpPath) 542 if (tmpPath)
543 { 543 {
544 WorkingDirectory[FILESYSTEM_NATIVE] = tmpPath; 544 WorkingDirectory[FILESYSTEM_NATIVE] = tmpPath;
545 delete [] tmpPath; 545 delete [] tmpPath;
546 } 546 }
547 #else 547 #else
548 u32 pathSize=256; 548 u32 pathSize=256;
549 char *tmpPath = new char[pathSize]; 549 char *tmpPath = new char[pathSize];
550 while ((pathSize < (1<<16)) && !(getcwd(tmpPath,pathSize))) 550 while ((pathSize < (1<<16)) && !(getcwd(tmpPath,pathSize)))
551 { 551 {
552 delete [] tmpPath; 552 delete [] tmpPath;
553 pathSize *= 2; 553 pathSize *= 2;
554 tmpPath = new char[pathSize]; 554 tmpPath = new char[pathSize];
555 } 555 }
556 if (tmpPath) 556 if (tmpPath)
557 { 557 {
558 WorkingDirectory[FILESYSTEM_NATIVE] = tmpPath; 558 WorkingDirectory[FILESYSTEM_NATIVE] = tmpPath;
559 delete [] tmpPath; 559 delete [] tmpPath;
560 } 560 }
561 #endif 561 #endif
562 #endif 562 #endif
563 563
564 WorkingDirectory[type].validate(); 564 WorkingDirectory[type].validate();
565 } 565 }
566 566
567 return WorkingDirectory[type]; 567 return WorkingDirectory[type];
568} 568}
569 569
570 570
571//! Changes the current Working Directory to the given string. 571//! Changes the current Working Directory to the given string.
572bool CFileSystem::changeWorkingDirectoryTo(const io::path& newDirectory) 572bool CFileSystem::changeWorkingDirectoryTo(const io::path& newDirectory)
573{ 573{
574 bool success=false; 574 bool success=false;
575 575
576 if (FileSystemType != FILESYSTEM_NATIVE) 576 if (FileSystemType != FILESYSTEM_NATIVE)
577 { 577 {
578 WorkingDirectory[FILESYSTEM_VIRTUAL] = newDirectory; 578 WorkingDirectory[FILESYSTEM_VIRTUAL] = newDirectory;
579 // is this empty string constant really intended? 579 // is this empty string constant really intended?
580 flattenFilename(WorkingDirectory[FILESYSTEM_VIRTUAL], _IRR_TEXT("")); 580 flattenFilename(WorkingDirectory[FILESYSTEM_VIRTUAL], _IRR_TEXT(""));
581 success = true; 581 success = true;
582 } 582 }
583 else 583 else
584 { 584 {
585 WorkingDirectory[FILESYSTEM_NATIVE] = newDirectory; 585 WorkingDirectory[FILESYSTEM_NATIVE] = newDirectory;
586 586
587#if defined(_IRR_WINDOWS_CE_PLATFORM_) 587#if defined(_IRR_WINDOWS_CE_PLATFORM_)
588 success = true; 588 success = true;
589#elif defined(_MSC_VER) 589#elif defined(_MSC_VER)
590 #if defined(_IRR_WCHAR_FILESYSTEM) 590 #if defined(_IRR_WCHAR_FILESYSTEM)
591 success = (_wchdir(newDirectory.c_str()) == 0); 591 success = (_wchdir(newDirectory.c_str()) == 0);
592 #else 592 #else
593 success = (_chdir(newDirectory.c_str()) == 0); 593 success = (_chdir(newDirectory.c_str()) == 0);
594 #endif 594 #endif
595#else 595#else
596 #if defined(_IRR_WCHAR_FILESYSTEM) 596 #if defined(_IRR_WCHAR_FILESYSTEM)
597 success = (_wchdir(newDirectory.c_str()) == 0); 597 success = (_wchdir(newDirectory.c_str()) == 0);
598 #else 598 #else
599 success = (chdir(newDirectory.c_str()) == 0); 599 success = (chdir(newDirectory.c_str()) == 0);
600 #endif 600 #endif
601#endif 601#endif
602 } 602 }
603 603
604 return success; 604 return success;
605} 605}
606 606
607 607
608io::path CFileSystem::getAbsolutePath(const io::path& filename) const 608io::path CFileSystem::getAbsolutePath(const io::path& filename) const
609{ 609{
610#if defined(_IRR_WINDOWS_CE_PLATFORM_) 610#if defined(_IRR_WINDOWS_CE_PLATFORM_)
611 return filename; 611 return filename;
612#elif defined(_IRR_WINDOWS_API_) 612#elif defined(_IRR_WINDOWS_API_)
613 fschar_t *p=0; 613 fschar_t *p=0;
614 fschar_t fpath[_MAX_PATH]; 614 fschar_t fpath[_MAX_PATH];
615 #if defined(_IRR_WCHAR_FILESYSTEM ) 615 #if defined(_IRR_WCHAR_FILESYSTEM )
616 p = _wfullpath(fpath, filename.c_str(), _MAX_PATH); 616 p = _wfullpath(fpath, filename.c_str(), _MAX_PATH);
617 core::stringw tmp(p); 617 core::stringw tmp(p);
618 tmp.replace(L'\\', L'/'); 618 tmp.replace(L'\\', L'/');
619 #else 619 #else
620 p = _fullpath(fpath, filename.c_str(), _MAX_PATH); 620 p = _fullpath(fpath, filename.c_str(), _MAX_PATH);
621 core::stringc tmp(p); 621 core::stringc tmp(p);
622 tmp.replace('\\', '/'); 622 tmp.replace('\\', '/');
623 #endif 623 #endif
624 return tmp; 624 return tmp;
625#elif (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_)) 625#elif (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_))
626 c8* p=0; 626 c8* p=0;
627 c8 fpath[4096]; 627 c8 fpath[4096];
628 fpath[0]=0; 628 fpath[0]=0;
629 p = realpath(filename.c_str(), fpath); 629 p = realpath(filename.c_str(), fpath);
630 if (!p) 630 if (!p)
631 { 631 {
632 // content in fpath is unclear at this point 632 // content in fpath is unclear at this point
633 if (!fpath[0]) // seems like fpath wasn't altered, use our best guess 633 if (!fpath[0]) // seems like fpath wasn't altered, use our best guess
634 { 634 {
635 io::path tmp(filename); 635 io::path tmp(filename);
636 return flattenFilename(tmp); 636 return flattenFilename(tmp);
637 } 637 }
638 else 638 else
639 return io::path(fpath); 639 return io::path(fpath);
640 } 640 }
641 if (filename[filename.size()-1]=='/') 641 if (filename[filename.size()-1]=='/')
642 return io::path(p)+_IRR_TEXT("/"); 642 return io::path(p)+_IRR_TEXT("/");
643 else 643 else
644 return io::path(p); 644 return io::path(p);
645#else 645#else
646 return io::path(filename); 646 return io::path(filename);
647#endif 647#endif
648} 648}
649 649
650 650
651//! returns the directory part of a filename, i.e. all until the first 651//! returns the directory part of a filename, i.e. all until the first
652//! slash or backslash, excluding it. If no directory path is prefixed, a '.' 652//! slash or backslash, excluding it. If no directory path is prefixed, a '.'
653//! is returned. 653//! is returned.
654io::path CFileSystem::getFileDir(const io::path& filename) const 654io::path CFileSystem::getFileDir(const io::path& filename) const
655{ 655{
656 // find last forward or backslash 656 // find last forward or backslash
657 s32 lastSlash = filename.findLast('/'); 657 s32 lastSlash = filename.findLast('/');
658 const s32 lastBackSlash = filename.findLast('\\'); 658 const s32 lastBackSlash = filename.findLast('\\');
659 lastSlash = lastSlash > lastBackSlash ? lastSlash : lastBackSlash; 659 lastSlash = lastSlash > lastBackSlash ? lastSlash : lastBackSlash;
660 660
661 if ((u32)lastSlash < filename.size()) 661 if ((u32)lastSlash < filename.size())
662 return filename.subString(0, lastSlash); 662 return filename.subString(0, lastSlash);
663 else 663 else
664 return _IRR_TEXT("."); 664 return _IRR_TEXT(".");
665} 665}
666 666
667 667
668//! returns the base part of a filename, i.e. all except for the directory 668//! returns the base part of a filename, i.e. all except for the directory
669//! part. If no directory path is prefixed, the full name is returned. 669//! part. If no directory path is prefixed, the full name is returned.
670io::path CFileSystem::getFileBasename(const io::path& filename, bool keepExtension) const 670io::path CFileSystem::getFileBasename(const io::path& filename, bool keepExtension) const
671{ 671{
672 // find last forward or backslash 672 // find last forward or backslash
673 s32 lastSlash = filename.findLast('/'); 673 s32 lastSlash = filename.findLast('/');
674 const s32 lastBackSlash = filename.findLast('\\'); 674 const s32 lastBackSlash = filename.findLast('\\');
675 lastSlash = core::max_(lastSlash, lastBackSlash); 675 lastSlash = core::max_(lastSlash, lastBackSlash);
676 676
677 // get number of chars after last dot 677 // get number of chars after last dot
678 s32 end = 0; 678 s32 end = 0;
679 if (!keepExtension) 679 if (!keepExtension)
680 { 680 {
681 // take care to search only after last slash to check only for 681 // take care to search only after last slash to check only for
682 // dots in the filename 682 // dots in the filename
683 end = filename.findLast('.'); 683 end = filename.findLast('.');
684 if (end == -1 || end < lastSlash) 684 if (end == -1 || end < lastSlash)
685 end=0; 685 end=0;
686 else 686 else
687 end = filename.size()-end; 687 end = filename.size()-end;
688 } 688 }
689 689
690 if ((u32)lastSlash < filename.size()) 690 if ((u32)lastSlash < filename.size())
691 return filename.subString(lastSlash+1, filename.size()-lastSlash-1-end); 691 return filename.subString(lastSlash+1, filename.size()-lastSlash-1-end);
692 else if (end != 0) 692 else if (end != 0)
693 return filename.subString(0, filename.size()-end); 693 return filename.subString(0, filename.size()-end);
694 else 694 else
695 return filename; 695 return filename;
696} 696}
697 697
698 698
699//! flatten a path and file name for example: "/you/me/../." becomes "/you" 699//! flatten a path and file name for example: "/you/me/../." becomes "/you"
700io::path& CFileSystem::flattenFilename(io::path& directory, const io::path& root) const 700io::path& CFileSystem::flattenFilename(io::path& directory, const io::path& root) const
701{ 701{
702 directory.replace('\\', '/'); 702 directory.replace('\\', '/');
703 if (directory.lastChar() != '/') 703 if (directory.lastChar() != '/')
704 directory.append('/'); 704 directory.append('/');
705 705
706 io::path dir; 706 io::path dir;
707 io::path subdir; 707 io::path subdir;
708 708
709 s32 lastpos = 0; 709 s32 lastpos = 0;
710 s32 pos = 0; 710 s32 pos = 0;
711 bool lastWasRealDir=false; 711 bool lastWasRealDir=false;
712 712
713 while ((pos = directory.findNext('/', lastpos)) >= 0) 713 while ((pos = directory.findNext('/', lastpos)) >= 0)
714 { 714 {
715 subdir = directory.subString(lastpos, pos - lastpos + 1); 715 subdir = directory.subString(lastpos, pos - lastpos + 1);
716 716
717 if (subdir == _IRR_TEXT("../")) 717 if (subdir == _IRR_TEXT("../"))
718 { 718 {
719 if (lastWasRealDir) 719 if (lastWasRealDir)
720 { 720 {
721 deletePathFromPath(dir, 2); 721 deletePathFromPath(dir, 2);
722 lastWasRealDir=(dir.size()!=0); 722 lastWasRealDir=(dir.size()!=0);
723 } 723 }
724 else 724 else
725 { 725 {
726 dir.append(subdir); 726 dir.append(subdir);
727 lastWasRealDir=false; 727 lastWasRealDir=false;
728 } 728 }
729 } 729 }
730 else if (subdir == _IRR_TEXT("/")) 730 else if (subdir == _IRR_TEXT("/"))
731 { 731 {
732 dir = root; 732 dir = root;
733 } 733 }
734 else if (subdir != _IRR_TEXT("./")) 734 else if (subdir != _IRR_TEXT("./"))
735 { 735 {
736 dir.append(subdir); 736 dir.append(subdir);
737 lastWasRealDir=true; 737 lastWasRealDir=true;
738 } 738 }
739 739
740 lastpos = pos + 1; 740 lastpos = pos + 1;
741 } 741 }
742 directory = dir; 742 directory = dir;
743 return directory; 743 return directory;
744} 744}
745 745
746 746
747//! Get the relative filename, relative to the given directory 747//! Get the relative filename, relative to the given directory
748path CFileSystem::getRelativeFilename(const path& filename, const path& directory) const 748path CFileSystem::getRelativeFilename(const path& filename, const path& directory) const
749{ 749{
750 if ( filename.empty() || directory.empty() ) 750 if ( filename.empty() || directory.empty() )
751 return filename; 751 return filename;
752 752
753 io::path path1, file, ext; 753 io::path path1, file, ext;
754 core::splitFilename(getAbsolutePath(filename), &path1, &file, &ext); 754 core::splitFilename(getAbsolutePath(filename), &path1, &file, &ext);
755 io::path path2(getAbsolutePath(directory)); 755 io::path path2(getAbsolutePath(directory));
756 core::list<io::path> list1, list2; 756 core::list<io::path> list1, list2;
757 path1.split(list1, _IRR_TEXT("/\\"), 2); 757 path1.split(list1, _IRR_TEXT("/\\"), 2);
758 path2.split(list2, _IRR_TEXT("/\\"), 2); 758 path2.split(list2, _IRR_TEXT("/\\"), 2);
759 u32 i=0; 759 u32 i=0;
760 core::list<io::path>::ConstIterator it1,it2; 760 core::list<io::path>::ConstIterator it1,it2;
761 it1=list1.begin(); 761 it1=list1.begin();
762 it2=list2.begin(); 762 it2=list2.begin();
763 763
764 #if defined (_IRR_WINDOWS_API_) 764 #if defined (_IRR_WINDOWS_API_)
765 fschar_t partition1 = 0, partition2 = 0; 765 fschar_t partition1 = 0, partition2 = 0;
766 io::path prefix1, prefix2; 766 io::path prefix1, prefix2;
767 if ( it1 != list1.end() ) 767 if ( it1 != list1.end() )
768 prefix1 = *it1; 768 prefix1 = *it1;
769 if ( it2 != list2.end() ) 769 if ( it2 != list2.end() )
770 prefix2 = *it2; 770 prefix2 = *it2;
771 if ( prefix1.size() > 1 && prefix1[1] == _IRR_TEXT(':') ) 771 if ( prefix1.size() > 1 && prefix1[1] == _IRR_TEXT(':') )
772 partition1 = core::locale_lower(prefix1[0]); 772 partition1 = core::locale_lower(prefix1[0]);
773 if ( prefix2.size() > 1 && prefix2[1] == _IRR_TEXT(':') ) 773 if ( prefix2.size() > 1 && prefix2[1] == _IRR_TEXT(':') )
774 partition2 = core::locale_lower(prefix2[0]); 774 partition2 = core::locale_lower(prefix2[0]);
775 775
776 // must have the same prefix or we can't resolve it to a relative filename 776 // must have the same prefix or we can't resolve it to a relative filename
777 if ( partition1 != partition2 ) 777 if ( partition1 != partition2 )
778 { 778 {
779 return filename; 779 return filename;
780 } 780 }
781 #endif 781 #endif
782 782
783 783
784 for (; i<list1.size() && i<list2.size() 784 for (; i<list1.size() && i<list2.size()
785#if defined (_IRR_WINDOWS_API_) 785#if defined (_IRR_WINDOWS_API_)
786 && (io::path(*it1).make_lower()==io::path(*it2).make_lower()) 786 && (io::path(*it1).make_lower()==io::path(*it2).make_lower())
787#else 787#else
788 && (*it1==*it2) 788 && (*it1==*it2)
789#endif 789#endif
790 ; ++i) 790 ; ++i)
791 { 791 {
792 ++it1; 792 ++it1;
793 ++it2; 793 ++it2;
794 } 794 }
795 path1=_IRR_TEXT(""); 795 path1=_IRR_TEXT("");
796 for (; i<list2.size(); ++i) 796 for (; i<list2.size(); ++i)
797 path1 += _IRR_TEXT("../"); 797 path1 += _IRR_TEXT("../");
798 while (it1 != list1.end()) 798 while (it1 != list1.end())
799 { 799 {
800 path1 += *it1++; 800 path1 += *it1++;
801 path1 += _IRR_TEXT('/'); 801 path1 += _IRR_TEXT('/');
802 } 802 }
803 path1 += file; 803 path1 += file;
804 if (ext.size()) 804 if (ext.size())
805 { 805 {
806 path1 += _IRR_TEXT('.'); 806 path1 += _IRR_TEXT('.');
807 path1 += ext; 807 path1 += ext;
808 } 808 }
809 return path1; 809 return path1;
810} 810}
811 811
812 812
813//! Sets the current file systen type 813//! Sets the current file systen type
814EFileSystemType CFileSystem::setFileListSystem(EFileSystemType listType) 814EFileSystemType CFileSystem::setFileListSystem(EFileSystemType listType)
815{ 815{
816 EFileSystemType current = FileSystemType; 816 EFileSystemType current = FileSystemType;
817 FileSystemType = listType; 817 FileSystemType = listType;
818 return current; 818 return current;
819} 819}
820 820
821 821
822//! Creates a list of files and directories in the current working directory 822//! Creates a list of files and directories in the current working directory
823IFileList* CFileSystem::createFileList() 823IFileList* CFileSystem::createFileList()
824{ 824{
825 CFileList* r = 0; 825 CFileList* r = 0;
826 io::path Path = getWorkingDirectory(); 826 io::path Path = getWorkingDirectory();
827 Path.replace('\\', '/'); 827 Path.replace('\\', '/');
828 if (Path.lastChar() != '/') 828 if (Path.lastChar() != '/')
829 Path.append('/'); 829 Path.append('/');
830 830
831 //! Construct from native filesystem 831 //! Construct from native filesystem
832 if (FileSystemType == FILESYSTEM_NATIVE) 832 if (FileSystemType == FILESYSTEM_NATIVE)
833 { 833 {
834 // -------------------------------------------- 834 // --------------------------------------------
835 //! Windows version 835 //! Windows version
836 #ifdef _IRR_WINDOWS_API_ 836 #ifdef _IRR_WINDOWS_API_
837 #if !defined ( _WIN32_WCE ) 837 #if !defined ( _WIN32_WCE )
838 838
839 r = new CFileList(Path, true, false); 839 r = new CFileList(Path, true, false);
840 840
841 // TODO: Should be unified once mingw adapts the proper types 841 // TODO: Should be unified once mingw adapts the proper types
842#if defined(__GNUC__) 842#if defined(__GNUC__)
843 long hFile; //mingw return type declaration 843 long hFile; //mingw return type declaration
844#else 844#else
845 intptr_t hFile; 845 intptr_t hFile;
846#endif 846#endif
847 847
848 struct _tfinddata_t c_file; 848 struct _tfinddata_t c_file;
849 if( (hFile = _tfindfirst( _T("*"), &c_file )) != -1L ) 849 if( (hFile = _tfindfirst( _T("*"), &c_file )) != -1L )
850 { 850 {
851 do 851 do
852 { 852 {
853 r->addItem(Path + c_file.name, 0, c_file.size, (_A_SUBDIR & c_file.attrib) != 0, 0); 853 r->addItem(Path + c_file.name, 0, c_file.size, (_A_SUBDIR & c_file.attrib) != 0, 0);
854 } 854 }
855 while( _tfindnext( hFile, &c_file ) == 0 ); 855 while( _tfindnext( hFile, &c_file ) == 0 );
856 856
857 _findclose( hFile ); 857 _findclose( hFile );
858 } 858 }
859 #endif 859 #endif
860 860
861 //TODO add drives 861 //TODO add drives
862 //entry.Name = "E:\\"; 862 //entry.Name = "E:\\";
863 //entry.isDirectory = true; 863 //entry.isDirectory = true;
864 //Files.push_back(entry); 864 //Files.push_back(entry);
865 #endif 865 #endif
866 866
867 // -------------------------------------------- 867 // --------------------------------------------
868 //! Linux version 868 //! Linux version
869 #if (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_)) 869 #if (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_))
870 870
871 871
872 r = new CFileList(Path, false, false); 872 r = new CFileList(Path, false, false);
873 873
874 r->addItem(Path + _IRR_TEXT(".."), 0, 0, true, 0); 874 r->addItem(Path + _IRR_TEXT(".."), 0, 0, true, 0);
875 875
876 //! We use the POSIX compliant methods instead of scandir 876 //! We use the POSIX compliant methods instead of scandir
877 DIR* dirHandle=opendir(Path.c_str()); 877 DIR* dirHandle=opendir(Path.c_str());
878 if (dirHandle) 878 if (dirHandle)
879 { 879 {
880 struct dirent *dirEntry; 880 struct dirent *dirEntry;
881 while ((dirEntry=readdir(dirHandle))) 881 while ((dirEntry=readdir(dirHandle)))
882 { 882 {
883 u32 size = 0; 883 u32 size = 0;
884 bool isDirectory = false; 884 bool isDirectory = false;
885 885
886 if((strcmp(dirEntry->d_name, ".")==0) || 886 if((strcmp(dirEntry->d_name, ".")==0) ||
887 (strcmp(dirEntry->d_name, "..")==0)) 887 (strcmp(dirEntry->d_name, "..")==0))
888 { 888 {
889 continue; 889 continue;
890 } 890 }
891 struct stat buf; 891 struct stat buf;
892 if (stat(dirEntry->d_name, &buf)==0) 892 if (stat(dirEntry->d_name, &buf)==0)
893 { 893 {
894 size = buf.st_size; 894 size = buf.st_size;
895 isDirectory = S_ISDIR(buf.st_mode); 895 isDirectory = S_ISDIR(buf.st_mode);
896 } 896 }
897 #if !defined(_IRR_SOLARIS_PLATFORM_) && !defined(__CYGWIN__) 897 #if !defined(_IRR_SOLARIS_PLATFORM_) && !defined(__CYGWIN__)
898 // only available on some systems 898 // only available on some systems
899 else 899 else
900 { 900 {
901 isDirectory = dirEntry->d_type == DT_DIR; 901 isDirectory = dirEntry->d_type == DT_DIR;
902 } 902 }
903 #endif 903 #endif
904 904
905 r->addItem(Path + dirEntry->d_name, 0, size, isDirectory, 0); 905 r->addItem(Path + dirEntry->d_name, 0, size, isDirectory, 0);
906 } 906 }
907 closedir(dirHandle); 907 closedir(dirHandle);
908 } 908 }
909 #endif 909 #endif
910 } 910 }
911 else 911 else
912 { 912 {
913 //! create file list for the virtual filesystem 913 //! create file list for the virtual filesystem
914 r = new CFileList(Path, false, false); 914 r = new CFileList(Path, false, false);
915 915
916 //! add relative navigation 916 //! add relative navigation
917 SFileListEntry e2; 917 SFileListEntry e2;
918 SFileListEntry e3; 918 SFileListEntry e3;
919 919
920 //! PWD 920 //! PWD
921 r->addItem(Path + _IRR_TEXT("."), 0, 0, true, 0); 921 r->addItem(Path + _IRR_TEXT("."), 0, 0, true, 0);
922 922
923 //! parent 923 //! parent
924 r->addItem(Path + _IRR_TEXT(".."), 0, 0, true, 0); 924 r->addItem(Path + _IRR_TEXT(".."), 0, 0, true, 0);
925 925
926 //! merge archives 926 //! merge archives
927 for (u32 i=0; i < FileArchives.size(); ++i) 927 for (u32 i=0; i < FileArchives.size(); ++i)
928 { 928 {
929 const IFileList *merge = FileArchives[i]->getFileList(); 929 const IFileList *merge = FileArchives[i]->getFileList();
930 930
931 for (u32 j=0; j < merge->getFileCount(); ++j) 931 for (u32 j=0; j < merge->getFileCount(); ++j)
932 { 932 {
933 if (core::isInSameDirectory(Path, merge->getFullFileName(j)) == 0) 933 if (core::isInSameDirectory(Path, merge->getFullFileName(j)) == 0)
934 { 934 {
935 r->addItem(merge->getFullFileName(j), merge->getFileOffset(j), merge->getFileSize(j), merge->isDirectory(j), 0); 935 r->addItem(merge->getFullFileName(j), merge->getFileOffset(j), merge->getFileSize(j), merge->isDirectory(j), 0);
936 } 936 }
937 } 937 }
938 } 938 }
939 } 939 }
940 940
941 if (r) 941 if (r)
942 r->sort(); 942 r->sort();
943 return r; 943 return r;
944} 944}
945 945
946//! Creates an empty filelist 946//! Creates an empty filelist
947IFileList* CFileSystem::createEmptyFileList(const io::path& path, bool ignoreCase, bool ignorePaths) 947IFileList* CFileSystem::createEmptyFileList(const io::path& path, bool ignoreCase, bool ignorePaths)
948{ 948{
949 return new CFileList(path, ignoreCase, ignorePaths); 949 return new CFileList(path, ignoreCase, ignorePaths);
950} 950}
951 951
952 952
953//! determines if a file exists and would be able to be opened. 953//! determines if a file exists and would be able to be opened.
954bool CFileSystem::existFile(const io::path& filename) const 954bool CFileSystem::existFile(const io::path& filename) const
955{ 955{
956 for (u32 i=0; i < FileArchives.size(); ++i) 956 for (u32 i=0; i < FileArchives.size(); ++i)
957 if (FileArchives[i]->getFileList()->findFile(filename)!=-1) 957 if (FileArchives[i]->getFileList()->findFile(filename)!=-1)
958 return true; 958 return true;
959 959
960#if defined(_IRR_WINDOWS_CE_PLATFORM_) 960#if defined(_IRR_WINDOWS_CE_PLATFORM_)
961#if defined(_IRR_WCHAR_FILESYSTEM) 961#if defined(_IRR_WCHAR_FILESYSTEM)
962 HANDLE hFile = CreateFileW(filename.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); 962 HANDLE hFile = CreateFileW(filename.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
963#else 963#else
964 HANDLE hFile = CreateFileW(core::stringw(filename).c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); 964 HANDLE hFile = CreateFileW(core::stringw(filename).c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
965#endif 965#endif
966 if (hFile == INVALID_HANDLE_VALUE) 966 if (hFile == INVALID_HANDLE_VALUE)
967 return false; 967 return false;
968 else 968 else
969 { 969 {
970 CloseHandle(hFile); 970 CloseHandle(hFile);
971 return true; 971 return true;
972 } 972 }
973#else 973#else
974 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; 974 _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
975#if defined(_MSC_VER) 975#if defined(_MSC_VER)
976 #if defined(_IRR_WCHAR_FILESYSTEM) 976 #if defined(_IRR_WCHAR_FILESYSTEM)
977 return (_waccess(filename.c_str(), 0) != -1); 977 return (_waccess(filename.c_str(), 0) != -1);
978 #else 978 #else
979 return (_access(filename.c_str(), 0) != -1); 979 return (_access(filename.c_str(), 0) != -1);
980 #endif 980 #endif
981#elif defined(F_OK) 981#elif defined(F_OK)
982 #if defined(_IRR_WCHAR_FILESYSTEM) 982 #if defined(_IRR_WCHAR_FILESYSTEM)
983 return (_waccess(filename.c_str(), F_OK) != -1); 983 return (_waccess(filename.c_str(), F_OK) != -1);
984 #else 984 #else
985 return (access(filename.c_str(), F_OK) != -1); 985 return (access(filename.c_str(), F_OK) != -1);
986 #endif 986 #endif
987#else 987#else
988 return (access(filename.c_str(), 0) != -1); 988 return (access(filename.c_str(), 0) != -1);
989#endif 989#endif
990#endif 990#endif
991} 991}
992 992
993 993
994//! Creates a XML Reader from a file. 994//! Creates a XML Reader from a file.
995IXMLReader* CFileSystem::createXMLReader(const io::path& filename) 995IXMLReader* CFileSystem::createXMLReader(const io::path& filename)
996{ 996{
997 IReadFile* file = createAndOpenFile(filename); 997 IReadFile* file = createAndOpenFile(filename);
998 if (!file) 998 if (!file)
999 return 0; 999 return 0;
1000 1000
1001 IXMLReader* reader = createXMLReader(file); 1001 IXMLReader* reader = createXMLReader(file);
1002 file->drop(); 1002 file->drop();
1003 return reader; 1003 return reader;
1004} 1004}
1005 1005
1006 1006
1007//! Creates a XML Reader from a file. 1007//! Creates a XML Reader from a file.
1008IXMLReader* CFileSystem::createXMLReader(IReadFile* file) 1008IXMLReader* CFileSystem::createXMLReader(IReadFile* file)
1009{ 1009{
1010 if (!file) 1010 if (!file)
1011 return 0; 1011 return 0;
1012 1012
1013 return createIXMLReader(file); 1013 return createIXMLReader(file);
1014} 1014}
1015 1015
1016 1016
1017//! Creates a XML Reader from a file. 1017//! Creates a XML Reader from a file.
1018IXMLReaderUTF8* CFileSystem::createXMLReaderUTF8(const io::path& filename) 1018IXMLReaderUTF8* CFileSystem::createXMLReaderUTF8(const io::path& filename)
1019{ 1019{
1020 IReadFile* file = createAndOpenFile(filename); 1020 IReadFile* file = createAndOpenFile(filename);
1021 if (!file) 1021 if (!file)
1022 return 0; 1022 return 0;
1023 1023
1024 IXMLReaderUTF8* reader = createIXMLReaderUTF8(file); 1024 IXMLReaderUTF8* reader = createIXMLReaderUTF8(file);
1025 file->drop(); 1025 file->drop();
1026 return reader; 1026 return reader;
1027} 1027}
1028 1028
1029 1029
1030//! Creates a XML Reader from a file. 1030//! Creates a XML Reader from a file.
1031IXMLReaderUTF8* CFileSystem::createXMLReaderUTF8(IReadFile* file) 1031IXMLReaderUTF8* CFileSystem::createXMLReaderUTF8(IReadFile* file)
1032{ 1032{
1033 if (!file) 1033 if (!file)
1034 return 0; 1034 return 0;
1035 1035
1036 return createIXMLReaderUTF8(file); 1036 return createIXMLReaderUTF8(file);
1037} 1037}
1038 1038
1039 1039
1040//! Creates a XML Writer from a file. 1040//! Creates a XML Writer from a file.
1041IXMLWriter* CFileSystem::createXMLWriter(const io::path& filename) 1041IXMLWriter* CFileSystem::createXMLWriter(const io::path& filename)
1042{ 1042{
1043 IWriteFile* file = createAndWriteFile(filename); 1043 IWriteFile* file = createAndWriteFile(filename);
1044 IXMLWriter* writer = 0; 1044 IXMLWriter* writer = 0;
1045 if (file) 1045 if (file)
1046 { 1046 {
1047 writer = createXMLWriter(file); 1047 writer = createXMLWriter(file);
1048 file->drop(); 1048 file->drop();
1049 } 1049 }
1050 return writer; 1050 return writer;
1051} 1051}
1052 1052
1053 1053
1054//! Creates a XML Writer from a file. 1054//! Creates a XML Writer from a file.
1055IXMLWriter* CFileSystem::createXMLWriter(IWriteFile* file) 1055IXMLWriter* CFileSystem::createXMLWriter(IWriteFile* file)
1056{ 1056{
1057 return new CXMLWriter(file); 1057 return new CXMLWriter(file);
1058} 1058}
1059 1059
1060 1060
1061//! creates a filesystem which is able to open files from the ordinary file system, 1061//! creates a filesystem which is able to open files from the ordinary file system,
1062//! and out of zipfiles, which are able to be added to the filesystem. 1062//! and out of zipfiles, which are able to be added to the filesystem.
1063IFileSystem* createFileSystem() 1063IFileSystem* createFileSystem()
1064{ 1064{
1065 return new CFileSystem(); 1065 return new CFileSystem();
1066} 1066}
1067 1067
1068 1068
1069//! Creates a new empty collection of attributes, usable for serialization and more. 1069//! Creates a new empty collection of attributes, usable for serialization and more.
1070IAttributes* CFileSystem::createEmptyAttributes(video::IVideoDriver* driver) 1070IAttributes* CFileSystem::createEmptyAttributes(video::IVideoDriver* driver)
1071{ 1071{
1072 return new CAttributes(driver); 1072 return new CAttributes(driver);
1073} 1073}
1074 1074
1075 1075
1076} // end namespace irr 1076} // end namespace irr
1077} // end namespace io 1077} // end namespace io
1078 1078