@@ -28,11 +28,18 @@ with this program; if not, write to the Free Software Foundation, Inc.,
2828#include " log.h"
2929#include " config.h"
3030#include " porting.h"
31+ #ifndef SERVER
32+ #include " irr_ptr.h"
33+ #endif
3134
3235namespace fs
3336{
3437
35- #ifdef _WIN32 // WINDOWS
38+ #ifdef _WIN32
39+
40+ /* **********
41+ * Windows *
42+ ***********/
3643
3744#define _WIN32_WINNT 0x0501
3845#include < windows.h>
@@ -201,7 +208,11 @@ std::string CreateTempFile()
201208 return path;
202209}
203210
204- #else // POSIX
211+ #else
212+
213+ /* ********
214+ * POSIX *
215+ *********/
205216
206217#include < sys/types.h>
207218#include < dirent.h>
@@ -392,6 +403,10 @@ std::string CreateTempFile()
392403
393404#endif
394405
406+ /* ***************************
407+ * portable implementations *
408+ ****************************/
409+
395410void GetRecursiveDirs (std::vector<std::string> &dirs, const std::string &dir)
396411{
397412 static const std::set<char > chars_to_ignore = { ' _' , ' .' };
@@ -753,69 +768,66 @@ bool safeWriteToFile(const std::string &path, const std::string &content)
753768 return true ;
754769}
755770
771+ #ifndef SERVER
756772bool extractZipFile (io::IFileSystem *fs, const char *filename, const std::string &destination)
757773{
758- if (!fs->addFileArchive (filename, false , false , io::EFAT_ZIP)) {
774+ // Be careful here not to touch the global file hierarchy in Irrlicht
775+ // since this function needs to be thread-safe!
776+
777+ io::IArchiveLoader *zip_loader = nullptr ;
778+ for (u32 i = 0 ; i < fs->getArchiveLoaderCount (); i++) {
779+ if (fs->getArchiveLoader (i)->isALoadableFileFormat (io::EFAT_ZIP)) {
780+ zip_loader = fs->getArchiveLoader (i);
781+ break ;
782+ }
783+ }
784+ if (!zip_loader) {
785+ warningstream << " fs::extractZipFile(): Irrlicht said it doesn't support ZIPs." << std::endl;
759786 return false ;
760787 }
761788
762- sanity_check (fs->getFileArchiveCount () > 0 );
763-
764- /* *********************************************************************/
765- /* WARNING this is not threadsafe!! */
766- /* *********************************************************************/
767- io::IFileArchive* opened_zip = fs->getFileArchive (fs->getFileArchiveCount () - 1 );
768-
789+ irr_ptr<io::IFileArchive> opened_zip (zip_loader->createArchive (filename, false , false ));
769790 const io::IFileList* files_in_zip = opened_zip->getFileList ();
770791
771- unsigned int number_of_files = files_in_zip->getFileCount ();
772-
773- for (unsigned int i=0 ; i < number_of_files; i++) {
774- std::string fullpath = destination;
775- fullpath += DIR_DELIM;
792+ for (u32 i = 0 ; i < files_in_zip->getFileCount (); i++) {
793+ std::string fullpath = destination + DIR_DELIM;
776794 fullpath += files_in_zip->getFullFileName (i).c_str ();
777795 std::string fullpath_dir = fs::RemoveLastPathComponent (fullpath);
778796
779- if (!files_in_zip->isDirectory (i)) {
780- if (!fs::PathExists (fullpath_dir) && !fs::CreateAllDirs (fullpath_dir)) {
781- fs->removeFileArchive (fs->getFileArchiveCount ()-1 );
782- return false ;
783- }
784-
785- io::IReadFile* toread = opened_zip->createAndOpenFile (i);
797+ if (files_in_zip->isDirectory (i))
798+ continue ; // ignore, we create dirs as necessary
786799
787- FILE *targetfile = fopen (fullpath.c_str ()," wb" );
800+ if (!fs::PathExists (fullpath_dir) && !fs::CreateAllDirs (fullpath_dir))
801+ return false ;
788802
789- if (targetfile == NULL ) {
790- fs->removeFileArchive (fs->getFileArchiveCount ()-1 );
791- return false ;
792- }
803+ irr_ptr<io::IReadFile> toread (opened_zip->createAndOpenFile (i));
793804
794- char read_buffer[1024 ];
795- long total_read = 0 ;
805+ std::ofstream os (fullpath.c_str (), std::ios::binary);
806+ if (!os.good ())
807+ return false ;
796808
797- while (total_read < toread->getSize ()) {
809+ char buffer[4096 ];
810+ long total_read = 0 ;
798811
799- unsigned int bytes_read =
800- toread->read (read_buffer,sizeof (read_buffer));
801- if ((bytes_read == 0 ) ||
802- (fwrite (read_buffer, 1 , bytes_read, targetfile) != bytes_read))
803- {
804- fclose (targetfile);
805- fs->removeFileArchive (fs->getFileArchiveCount () - 1 );
806- return false ;
807- }
808- total_read += bytes_read;
812+ while (total_read < toread->getSize ()) {
813+ long bytes_read = toread->read (buffer, sizeof (buffer));
814+ bool error = true ;
815+ if (bytes_read != 0 ) {
816+ os.write (buffer, bytes_read);
817+ error = os.fail ();
809818 }
810-
811- fclose (targetfile);
819+ if (error) {
820+ os.close ();
821+ remove (fullpath.c_str ());
822+ return false ;
823+ }
824+ total_read += bytes_read;
812825 }
813-
814826 }
815827
816- fs->removeFileArchive (fs->getFileArchiveCount () - 1 );
817828 return true ;
818829}
830+ #endif
819831
820832bool ReadFile (const std::string &path, std::string &out)
821833{
@@ -829,7 +841,7 @@ bool ReadFile(const std::string &path, std::string &out)
829841 is.seekg (0 );
830842 is.read (&out[0 ], size);
831843
832- return true ;
844+ return !is. fail () ;
833845}
834846
835847bool Rename (const std::string &from, const std::string &to)
0 commit comments