• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

FileList.cpp

Go to the documentation of this file.
00001 #include "FileList.h"
00002 #include <stdio.h> // RAKNET_DEBUG_PRINTF
00003 #include "RakAssert.h"
00004 #if defined(_WIN32) || defined(__CYGWIN__)
00005         #include <io.h>
00006 #elif !defined ( __APPLE__ ) && !defined ( __APPLE_CC__ ) && !defined ( __PPC__ ) && !defined ( __FreeBSD__ )
00007         #include <sys/io.h>
00008 #endif
00009 #include "DS_Queue.h"
00010 #ifdef _WIN32 
00011 // For mkdir
00012 #include <direct.h>
00013 #else
00014 #include <sys/stat.h>
00015 #endif
00016 //#include "SHA1.h"
00017 #include "StringCompressor.h"
00018 #include "BitStream.h"
00019 #include "FileOperations.h"
00020 #include "SuperFastHash.h"
00021 #include "RakAssert.h"
00022 #include "LinuxStrings.h"
00023 
00024 #define MAX_FILENAME_LENGTH 512
00025 static const unsigned HASH_LENGTH=sizeof(unsigned int);
00026 
00027 // alloca
00028 #if defined(_XBOX) || defined(X360)
00029 #elif defined(_WIN32)
00030 #include <malloc.h>
00031 #else
00032 #if !defined ( __FreeBSD__ )
00033 #include <alloca.h>
00034 #endif
00035 #include <unistd.h>
00036 #include <stdlib.h>
00037 #include <sys/stat.h>
00038 #include "_FindFirst.h"
00039 #include <stdint.h> //defines intptr_t
00040 #endif
00041 
00042 #include "RakAlloca.h"
00043 
00044 //int RAK_DLL_EXPORT FileListNodeComp( char * const &key, const FileListNode &data )
00045 //{
00046 //      return strcmp(key, data.filename);
00047 //}
00048 
00049 
00050 #ifdef _MSC_VER
00051 #pragma warning( push )
00052 #endif
00053 
00055 void FLP_Printf::OnAddFilesFromDirectoryStarted(FileList *fileList, char *dir) {
00056         (void) fileList;
00057         RAKNET_DEBUG_PRINTF("Adding files from directory %s\n",dir);}
00058 
00060 void FLP_Printf::OnDirectory(FileList *fileList, char *dir, unsigned int directoriesRemaining) {
00061         (void) fileList;
00062         RAKNET_DEBUG_PRINTF("Adding %s. %i remaining.\n", dir, directoriesRemaining);}  
00063 
00064 FileList::FileList()
00065 {
00066         callback=0;
00067 }
00068 FileList::~FileList()
00069 {
00070         Clear();
00071 }
00072 void FileList::AddFile(const char *filepath, const char *filename, FileListNodeContext context)
00073 {
00074         if (filepath==0 || filename==0)
00075                 return;
00076 
00077         char *data;
00078         //std::fstream file;
00079         //file.open(filename, std::ios::in | std::ios::binary);
00080 
00081         FILE *fp = fopen(filepath, "rb");
00082         if (fp==0)
00083                 return;
00084         fseek(fp, 0, SEEK_END);
00085         int length = ftell(fp);
00086         fseek(fp, 0, SEEK_SET);
00087 
00088         if (length > (int) ((unsigned int)-1 / 8))
00089         {
00090                 // If this assert hits, split up your file. You could also change BitSize_t in RakNetTypes.h to unsigned long long but this is not recommended for performance reasons
00091                 RakAssert("Cannot add files over 536 MB" && 0);
00092                 fclose(fp);
00093                 return;
00094         }
00095 
00096 
00097 #if !defined(_XBOX) && !defined(_X360)
00098         bool usedAlloca=false;
00099         if (length < MAX_ALLOCA_STACK_ALLOCATION)
00100         {
00101                 data = ( char* ) alloca( length );
00102                 usedAlloca=true;
00103         }
00104         else
00105 #endif
00106         {
00107                 data = (char*) rakMalloc_Ex( length, __FILE__, __LINE__ );
00108         }
00109 
00110         fread(data, 1, length, fp);
00111         AddFile(filename, filepath, data, length, length, context);
00112         fclose(fp);
00113 
00114 #if !defined(_XBOX) && !defined(_X360)
00115         if (usedAlloca==false)
00116 #endif
00117                 rakFree_Ex(data, __FILE__, __LINE__ );
00118 
00119 }
00120 void FileList::AddFile(const char *filename, const char *fullPathToFile, const char *data, const unsigned dataLength, const unsigned fileLength, FileListNodeContext context, bool isAReference)
00121 {
00122         if (filename==0)
00123                 return;
00124         if (strlen(filename)>MAX_FILENAME_LENGTH)
00125         {
00126                 // Should be enough for anyone
00127                 RakAssert(0);
00128                 return;
00129         }
00130         // If adding a reference, do not send data
00131         RakAssert(isAReference==false || data==0);
00132         // Avoid duplicate insertions unless the data is different, in which case overwrite the old data
00133         unsigned i;
00134         for (i=0; i<fileList.Size();i++)
00135         {
00136                 if (strcmp(fileList[i].filename, filename)==0)
00137                 {
00138                         if (fileList[i].fileLengthBytes==fileLength && fileList[i].dataLengthBytes==dataLength &&
00139                                 (dataLength==0 || fileList[i].data==0 ||
00140                                 memcmp(fileList[i].data, data, dataLength)==0
00141                                 ))
00142                                 // Exact same file already here
00143                                 return;
00144 
00145                         // File of the same name, but different contents, so overwrite
00146                         rakFree_Ex(fileList[i].data, __FILE__, __LINE__ );
00147                         fileList.RemoveAtIndex(i);
00148                         break;
00149                 }
00150         }
00151 
00152         FileListNode n;
00153 //      size_t fileNameLen = strlen(filename);
00154         if (dataLength && data)
00155         {
00156                 n.data=(char*) rakMalloc_Ex( dataLength, __FILE__, __LINE__ );
00157                 memcpy(n.data, data, dataLength);
00158         }
00159         else
00160                 n.data=0;
00161         n.dataLengthBytes=dataLength;
00162         n.fileLengthBytes=fileLength;
00163         n.isAReference=isAReference;
00164         n.context=context;
00165         n.filename=filename;
00166         n.fullPathToFile=fullPathToFile;
00167                 
00168         fileList.Insert(n, __FILE__, __LINE__);
00169 }
00170 void FileList::AddFilesFromDirectory(const char *applicationDirectory, const char *subDirectory, bool writeHash, bool writeData, bool recursive, FileListNodeContext context)
00171 {
00172         DataStructures::Queue<char*> dirList;
00173         char root[260];
00174         char fullPath[520];
00175         _finddata_t fileInfo;
00176         intptr_t dir;
00177         FILE *fp;
00178         char *dirSoFar, *fileData;
00179         dirSoFar=(char*) rakMalloc_Ex( 520, __FILE__, __LINE__ );
00180 
00181         if (applicationDirectory)
00182                 strcpy(root, applicationDirectory);
00183         else
00184                 root[0]=0;
00185 
00186         int rootLen=(int)strlen(root);
00187         if (rootLen)
00188         {
00189                 strcpy(dirSoFar, root);
00190                 if (FixEndingSlash(dirSoFar))
00191                         rootLen++;
00192         }
00193         else
00194                 dirSoFar[0]=0;
00195         
00196         if (subDirectory)
00197         {
00198                 strcat(dirSoFar, subDirectory);
00199                 FixEndingSlash(dirSoFar);
00200         }
00201         if (callback)
00202                 callback->OnAddFilesFromDirectoryStarted(this, dirSoFar);
00203         // RAKNET_DEBUG_PRINTF("Adding files from directory %s\n",dirSoFar);
00204         dirList.Push(dirSoFar, __FILE__, __LINE__ );
00205         while (dirList.Size())
00206         {
00207                 dirSoFar=dirList.Pop();
00208                 strcpy(fullPath, dirSoFar);
00209                 // Changed from *.* to * for Linux compatibility
00210                 strcat(fullPath, "*");
00211 
00212 
00213                 dir=_findfirst(fullPath, &fileInfo );
00214                 if (dir==-1)
00215                 {
00216                         _findclose(dir);
00217                         rakFree_Ex(dirSoFar, __FILE__, __LINE__ );
00218                         unsigned i;
00219                         for (i=0; i < dirList.Size(); i++)
00220                                 rakFree_Ex(dirList[i], __FILE__, __LINE__ );
00221                         return;
00222                 }
00223 
00224 //              RAKNET_DEBUG_PRINTF("Adding %s. %i remaining.\n", fullPath, dirList.Size());
00225                 if (callback)
00226                         callback->OnDirectory(this, fullPath, dirList.Size());
00227 
00228                 do
00229                 {
00230                     // no guarantee these entries are first...
00231                     if (strcmp("." , fileInfo.name) == 0 ||
00232                         strcmp("..", fileInfo.name) == 0)
00233                     {
00234                         continue;
00235                     }
00236                     
00237                         if ((fileInfo.attrib & (_A_HIDDEN | _A_SUBDIR | _A_SYSTEM))==0)
00238                         {
00239                                 strcpy(fullPath, dirSoFar);
00240                                 strcat(fullPath, fileInfo.name);
00241                                 fileData=0;
00242 
00243                                 if (callback)
00244                                         callback->OnFile(this, dirSoFar, fileInfo.name, fileInfo.size);
00245 
00246                                 if (writeData && writeHash)
00247                                 {
00248                                         fileData= (char*) rakMalloc_Ex( fileInfo.size+HASH_LENGTH, __FILE__, __LINE__ );
00249                                         fp = fopen(fullPath, "rb");
00250                                         fread(fileData+HASH_LENGTH, fileInfo.size, 1, fp);
00251                                         fclose(fp);
00252 
00253                                         unsigned int hash = SuperFastHash(fileData+HASH_LENGTH, fileInfo.size);
00254                                         if (RakNet::BitStream::DoEndianSwap())
00255                                                 RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &hash, sizeof(hash));
00256                                         memcpy(fileData, &hash, HASH_LENGTH);
00257 
00258 //                                      sha1.Reset();
00259 //                                      sha1.Update( ( unsigned char* ) fileData+HASH_LENGTH, fileInfo.size );
00260 //                                      sha1.Final();
00261 //                                      memcpy(fileData, sha1.GetHash(), HASH_LENGTH);
00262                                         // File data and hash
00263                                         AddFile((const char*)fullPath+rootLen, fullPath, fileData, fileInfo.size+HASH_LENGTH, fileInfo.size, context);
00264                                 }
00265                                 else if (writeHash)
00266                                 {
00267 //                                      sha1.Reset();
00268 //                                      sha1.HashFile((char*)fullPath);
00269 //                                      sha1.Final();
00270 
00271                                         unsigned int hash = SuperFastHashFile(fullPath);
00272                                         if (RakNet::BitStream::DoEndianSwap())
00273                                                 RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &hash, sizeof(hash));
00274 
00275                                         // Hash only
00276                                 //      AddFile((const char*)fullPath+rootLen, (const char*)sha1.GetHash(), HASH_LENGTH, fileInfo.size, context);
00277                                         AddFile((const char*)fullPath+rootLen, fullPath, (const char*)&hash, HASH_LENGTH, fileInfo.size, context);
00278                                 }
00279                                 else if (writeData)
00280                                 {
00281                                         fileData= (char*) rakMalloc_Ex( fileInfo.size, __FILE__, __LINE__ );
00282                                         fp = fopen(fullPath, "rb");
00283                                         fread(fileData, fileInfo.size, 1, fp);
00284                                         fclose(fp);
00285 
00286                                         // File data only
00287                                         AddFile(fullPath+rootLen, fullPath, fileData, fileInfo.size, fileInfo.size, context);
00288                                 }
00289                                 else
00290                                 {
00291                                         // Just the filename
00292                                         AddFile(fullPath+rootLen, fullPath, 0, 0, fileInfo.size, context);
00293                                 }
00294 
00295                                 if (fileData)
00296                                         rakFree_Ex(fileData, __FILE__, __LINE__ );
00297                         }
00298                         else if ((fileInfo.attrib & _A_SUBDIR) && (fileInfo.attrib & (_A_HIDDEN | _A_SYSTEM))==0 && recursive)
00299                         {
00300                                 char *newDir=(char*) rakMalloc_Ex( 520, __FILE__, __LINE__ );
00301                                 strcpy(newDir, dirSoFar);
00302                                 strcat(newDir, fileInfo.name);
00303                                 strcat(newDir, "/");
00304                                 dirList.Push(newDir, __FILE__, __LINE__ );
00305                         }
00306 
00307                 } while (_findnext(dir, &fileInfo ) != -1);
00308 
00309                 _findclose(dir);
00310                 rakFree_Ex(dirSoFar, __FILE__, __LINE__ );
00311         }
00312 }
00313 void FileList::Clear(void)
00314 {
00315         unsigned i;
00316         for (i=0; i<fileList.Size(); i++)
00317         {
00318                 rakFree_Ex(fileList[i].data, __FILE__, __LINE__ );
00319         }
00320         fileList.Clear(false, __FILE__, __LINE__);
00321 }
00322 void FileList::Serialize(RakNet::BitStream *outBitStream)
00323 {
00324         outBitStream->WriteCompressed(fileList.Size());
00325         unsigned i;
00326         for (i=0; i < fileList.Size(); i++)
00327         {
00328                 outBitStream->WriteCompressed(fileList[i].context.op);
00329                 outBitStream->WriteCompressed(fileList[i].context.fileId);
00330                 stringCompressor->EncodeString(fileList[i].filename.C_String(), MAX_FILENAME_LENGTH, outBitStream);
00331                 outBitStream->Write((bool)(fileList[i].dataLengthBytes>0==true));
00332                 if (fileList[i].dataLengthBytes>0)
00333                 {
00334                         outBitStream->WriteCompressed(fileList[i].dataLengthBytes);
00335                         outBitStream->Write(fileList[i].data, fileList[i].dataLengthBytes);
00336                 }
00337 
00338                 outBitStream->Write((bool)(fileList[i].fileLengthBytes==fileList[i].dataLengthBytes));
00339                 if (fileList[i].fileLengthBytes!=fileList[i].dataLengthBytes)
00340                         outBitStream->WriteCompressed(fileList[i].fileLengthBytes);
00341         }
00342 }
00343 bool FileList::Deserialize(RakNet::BitStream *inBitStream)
00344 {
00345         bool b, dataLenNonZero=false, fileLenMatchesDataLen=false;
00346         char filename[512];
00347         unsigned int fileListSize;
00348         FileListNode n;
00349         b=inBitStream->ReadCompressed(fileListSize);
00350 #ifdef _DEBUG
00351         RakAssert(b);
00352         RakAssert(fileListSize < 10000);
00353 #endif
00354         if (b==false || fileListSize > 10000)
00355                 return false; // Sanity check
00356         Clear();        
00357         unsigned i;
00358         for (i=0; i < fileListSize; i++)
00359         {
00360                 inBitStream->ReadCompressed(n.context.op);
00361                 inBitStream->ReadCompressed(n.context.fileId);
00362                 stringCompressor->DecodeString((char*)filename, MAX_FILENAME_LENGTH, inBitStream);
00363                 inBitStream->Read(dataLenNonZero);
00364                 if (dataLenNonZero)
00365                 {
00366                         inBitStream->ReadCompressed(n.dataLengthBytes);
00367                         // sanity check
00368                         if (n.dataLengthBytes>2000000000)
00369                         {
00370 #ifdef _DEBUG
00371                                 RakAssert(n.dataLengthBytes<=2000000000);
00372 #endif
00373                                 return false;
00374                         }
00375                         n.data=(char*) rakMalloc_Ex( (size_t) n.dataLengthBytes, __FILE__, __LINE__ );
00376                         inBitStream->Read(n.data, n.dataLengthBytes);
00377                 }
00378                 else
00379                 {
00380                         n.dataLengthBytes=0;
00381                         n.data=0;
00382                 }
00383                 
00384                 b=inBitStream->Read(fileLenMatchesDataLen);
00385                 if (fileLenMatchesDataLen)
00386                         n.fileLengthBytes=(unsigned) n.dataLengthBytes;
00387                 else
00388                         b=inBitStream->ReadCompressed(n.fileLengthBytes);
00389 #ifdef _DEBUG
00390                 RakAssert(b);
00391 #endif
00392                 if (b==0)
00393                 {
00394                         Clear();
00395                         return false;
00396                 }
00397                 n.filename=filename;
00398                 n.fullPathToFile=filename;
00399                 fileList.Insert(n, __FILE__, __LINE__);
00400         }
00401 
00402         return true;
00403 }
00404 void FileList::GetDeltaToCurrent(FileList *input, FileList *output, const char *dirSubset, const char *remoteSubdir)
00405 {
00406         // For all files in this list that do not match the input list, write them to the output list.
00407         // dirSubset allows checking only a portion of the files in this list.
00408         unsigned thisIndex, inputIndex;
00409         unsigned dirSubsetLen, localPathLen, remoteSubdirLen;
00410         bool match;
00411         if (dirSubset)
00412                 dirSubsetLen = (unsigned int) strlen(dirSubset);
00413         else
00414                 dirSubsetLen = 0;
00415         if (remoteSubdir && remoteSubdir[0])
00416         {
00417                 remoteSubdirLen=(unsigned int) strlen(remoteSubdir);
00418                 if (IsSlash(remoteSubdir[remoteSubdirLen-1]))
00419                         remoteSubdirLen--;
00420         }
00421         else
00422                 remoteSubdirLen=0;
00423 
00424         for (thisIndex=0; thisIndex < fileList.Size(); thisIndex++)
00425         {
00426                 localPathLen = (unsigned int) fileList[thisIndex].filename.GetLength();
00427                 while (localPathLen>0)
00428                 {
00429                         if (IsSlash(fileList[thisIndex].filename[localPathLen-1]))
00430                         {
00431                                 localPathLen--;
00432                                 break;
00433                         }
00434                         localPathLen--;
00435                 }
00436 
00437                 // fileList[thisIndex].filename has to match dirSubset and be shorter or equal to it in length.
00438                 if (dirSubsetLen>0 &&
00439                         (localPathLen<dirSubsetLen ||
00440                         _strnicmp(fileList[thisIndex].filename.C_String(), dirSubset, dirSubsetLen)!=0 ||
00441                         (localPathLen>dirSubsetLen && IsSlash(fileList[thisIndex].filename[dirSubsetLen])==false)))
00442                         continue;
00443 
00444                 match=false;
00445                 for (inputIndex=0; inputIndex < input->fileList.Size(); inputIndex++)
00446                 {
00447                         // If the filenames, hashes, and lengths match then skip this element in fileList.  Otherwise write it to output
00448                         if (_stricmp(input->fileList[inputIndex].filename.C_String()+remoteSubdirLen,fileList[thisIndex].filename.C_String()+dirSubsetLen)==0)
00449                         {
00450                                 match=true;
00451                                 if (input->fileList[inputIndex].fileLengthBytes==fileList[thisIndex].fileLengthBytes &&
00452                                         input->fileList[inputIndex].dataLengthBytes==fileList[thisIndex].dataLengthBytes &&
00453                                         memcmp(input->fileList[inputIndex].data,fileList[thisIndex].data,(size_t) fileList[thisIndex].dataLengthBytes)==0)
00454                                 {
00455                                         // File exists on both machines and is the same.
00456                                         break;
00457                                 }
00458                                 else
00459                                 {
00460                                         // File exists on both machines and is not the same.
00461                                         output->AddFile(fileList[thisIndex].filename, fileList[thisIndex].fullPathToFile, 0,0, fileList[thisIndex].fileLengthBytes, FileListNodeContext(0,0), false);
00462                                         break;
00463                                 }
00464                         }
00465                 }
00466                 if (match==false)
00467                 {
00468             // Other system does not have the file at all
00469                         output->AddFile(fileList[thisIndex].filename, fileList[thisIndex].fullPathToFile, 0,0, fileList[thisIndex].fileLengthBytes, FileListNodeContext(0,0), false);
00470                 }
00471         }
00472 }
00473 void FileList::ListMissingOrChangedFiles(const char *applicationDirectory, FileList *missingOrChangedFiles, bool alwaysWriteHash, bool neverWriteHash)
00474 {
00475         unsigned fileLength;
00476 //      CSHA1 sha1;
00477         FILE *fp;
00478         char fullPath[512];
00479         unsigned i;
00480 //      char *fileData;
00481 
00482         for (i=0; i < fileList.Size(); i++)
00483         {
00484                 strcpy(fullPath, applicationDirectory);
00485                 FixEndingSlash(fullPath);
00486                 strcat(fullPath,fileList[i].filename);
00487                 fp=fopen(fullPath, "rb");
00488                 if (fp==0)
00489                 {
00490                         missingOrChangedFiles->AddFile(fileList[i].filename, fileList[i].fullPathToFile, 0, 0, 0, FileListNodeContext(0,0), false);
00491                 }
00492                 else
00493                 {
00494                         fseek(fp, 0, SEEK_END);
00495                         fileLength = ftell(fp);
00496                         fseek(fp, 0, SEEK_SET);
00497 
00498                         if (fileLength != fileList[i].fileLengthBytes && alwaysWriteHash==false)
00499                         {
00500                                 missingOrChangedFiles->AddFile(fileList[i].filename, fileList[i].fullPathToFile, 0, 0, fileLength, FileListNodeContext(0,0), false);
00501                         }
00502                         else
00503                         {
00504 
00505 //                              fileData= (char*) rakMalloc_Ex( fileLength, __FILE__, __LINE__ );
00506 //                              fread(fileData, fileLength, 1, fp);
00507 
00508 //                              sha1.Reset();
00509 //                              sha1.Update( ( unsigned char* ) fileData, fileLength );
00510 //                              sha1.Final();
00511 
00512 //                              rakFree_Ex(fileData, __FILE__, __LINE__ );
00513 
00514                                 unsigned int hash = SuperFastHashFilePtr(fp);
00515                                 if (RakNet::BitStream::DoEndianSwap())
00516                                         RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &hash, sizeof(hash));
00517 
00518                                 //if (fileLength != fileList[i].fileLength || memcmp( sha1.GetHash(), fileList[i].data, HASH_LENGTH)!=0)
00519                                 if (fileLength != fileList[i].fileLengthBytes || memcmp( &hash, fileList[i].data, HASH_LENGTH)!=0)
00520                                 {
00521                                         if (neverWriteHash==false)
00522                                         //      missingOrChangedFiles->AddFile((const char*)fileList[i].filename, (const char*)sha1.GetHash(), HASH_LENGTH, fileLength, 0);
00523                                                 missingOrChangedFiles->AddFile((const char*)fileList[i].filename, (const char*)fileList[i].fullPathToFile, (const char *) &hash, HASH_LENGTH, fileLength, FileListNodeContext(0,0), false);
00524                                         else
00525                                                 missingOrChangedFiles->AddFile((const char*)fileList[i].filename, (const char*)fileList[i].fullPathToFile, 0, 0, fileLength, FileListNodeContext(0,0), false);
00526                                 }
00527                         }
00528                         fclose(fp);
00529                 }
00530         }
00531 }
00532 void FileList::PopulateDataFromDisk(const char *applicationDirectory, bool writeFileData, bool writeFileHash, bool removeUnknownFiles)
00533 {
00534         FILE *fp;
00535         char fullPath[512];
00536         unsigned i;
00537 //      CSHA1 sha1;
00538 
00539         i=0;
00540         while (i < fileList.Size())
00541         {
00542                 rakFree_Ex(fileList[i].data, __FILE__, __LINE__ );
00543                 strcpy(fullPath, applicationDirectory);
00544                 FixEndingSlash(fullPath);
00545                 strcat(fullPath,fileList[i].filename.C_String());
00546                 fp=fopen(fullPath, "rb");
00547                 if (fp)
00548                 {
00549                         if (writeFileHash || writeFileData)
00550                         {
00551                                 fseek(fp, 0, SEEK_END);
00552                                 fileList[i].fileLengthBytes = ftell(fp);
00553                                 fseek(fp, 0, SEEK_SET);
00554                                 if (writeFileHash)
00555                                 {
00556                                         if (writeFileData)
00557                                         {
00558                                                 // Hash + data so offset the data by HASH_LENGTH
00559                                                 fileList[i].data=(char*) rakMalloc_Ex( fileList[i].fileLengthBytes+HASH_LENGTH, __FILE__, __LINE__ );
00560                                                 fread(fileList[i].data+HASH_LENGTH, fileList[i].fileLengthBytes, 1, fp);
00561 //                                              sha1.Reset();
00562 //                                              sha1.Update((unsigned char*)fileList[i].data+HASH_LENGTH, fileList[i].fileLength);
00563 //                                              sha1.Final();
00564                                                 unsigned int hash = SuperFastHash(fileList[i].data+HASH_LENGTH, fileList[i].fileLengthBytes);
00565                                                 if (RakNet::BitStream::DoEndianSwap())
00566                                                         RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &hash, sizeof(hash));
00567 //                                              memcpy(fileList[i].data, sha1.GetHash(), HASH_LENGTH);
00568                                                 memcpy(fileList[i].data, &hash, HASH_LENGTH);
00569                                         }
00570                                         else
00571                                         {
00572                                                 // Hash only
00573                                                 fileList[i].dataLengthBytes=HASH_LENGTH;
00574                                                 if (fileList[i].fileLengthBytes < HASH_LENGTH)
00575                                                         fileList[i].data=(char*) rakMalloc_Ex( HASH_LENGTH, __FILE__, __LINE__ );
00576                                                 else
00577                                                         fileList[i].data=(char*) rakMalloc_Ex( fileList[i].fileLengthBytes, __FILE__, __LINE__ );
00578                                                 fread(fileList[i].data, fileList[i].fileLengthBytes, 1, fp);
00579                                 //              sha1.Reset();
00580                                 //              sha1.Update((unsigned char*)fileList[i].data, fileList[i].fileLength);
00581                                 //              sha1.Final();
00582                                                 unsigned int hash = SuperFastHash(fileList[i].data, fileList[i].fileLengthBytes);
00583                                                 if (RakNet::BitStream::DoEndianSwap())
00584                                                         RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &hash, sizeof(hash));
00585                                                 // memcpy(fileList[i].data, sha1.GetHash(), HASH_LENGTH);
00586                                                 memcpy(fileList[i].data, &hash, HASH_LENGTH);
00587                                         }
00588                                 }
00589                                 else
00590                                 {
00591                                         // Data only
00592                                         fileList[i].dataLengthBytes=fileList[i].fileLengthBytes;
00593                                         fileList[i].data=(char*) rakMalloc_Ex( fileList[i].fileLengthBytes, __FILE__, __LINE__ );
00594                                         fread(fileList[i].data, fileList[i].fileLengthBytes, 1, fp);
00595                                 }
00596 
00597                                 fclose(fp);
00598                                 i++;
00599                         }
00600                         else
00601                         {
00602                                 fileList[i].data=0;
00603                                 fileList[i].dataLengthBytes=0;
00604                         }
00605                 }
00606                 else
00607                 {
00608                         if (removeUnknownFiles)
00609                         {
00610                                 fileList.RemoveAtIndex(i);
00611                         }
00612                         else
00613                                 i++;                    
00614                 }
00615         }
00616 }
00617 void FileList::FlagFilesAsReferences(void)
00618 {
00619         for (unsigned int i=0; i < fileList.Size(); i++)
00620         {
00621                 fileList[i].isAReference=true;
00622                 fileList[i].dataLengthBytes=fileList[i].fileLengthBytes;
00623         }
00624 }
00625 void FileList::WriteDataToDisk(const char *applicationDirectory)
00626 {
00627         char fullPath[512];
00628         unsigned i,j;
00629 
00630         for (i=0; i < fileList.Size(); i++)
00631         {
00632                 strcpy(fullPath, applicationDirectory);
00633                 FixEndingSlash(fullPath);
00634                 strcat(fullPath,fileList[i].filename.C_String());
00635                 
00636                 // Security - Don't allow .. in the filename anywhere so you can't write outside of the root directory
00637                 for (j=1; j < fileList[i].filename.GetLength(); j++)
00638                 {
00639                         if (fileList[i].filename[j]=='.' && fileList[i].filename[j-1]=='.')
00640                         {
00641 #ifdef _DEBUG
00642                                 RakAssert(0);
00643 #endif
00644                                 // Just cancel the write entirely
00645                                 return;
00646                         }
00647                 }
00648 
00649                 WriteFileWithDirectories(fullPath, fileList[i].data, (unsigned int) fileList[i].dataLengthBytes);
00650         }
00651 }
00652 
00653 #ifdef _MSC_VER
00654 #pragma warning( disable : 4966 ) // unlink declared deprecated by Microsoft in order to make it harder to be cross platform.  I don't agree it's deprecated.
00655 #endif
00656 void FileList::DeleteFiles(const char *applicationDirectory)
00657 {
00658         char fullPath[512];
00659         unsigned i,j;
00660 
00661         for (i=0; i < fileList.Size(); i++)
00662         {
00663                 // The filename should not have .. in the path - if it does ignore it
00664                 for (j=1; j < fileList[i].filename.GetLength(); j++)
00665                 {
00666                         if (fileList[i].filename[j]=='.' && fileList[i].filename[j-1]=='.')
00667                         {
00668 #ifdef _DEBUG
00669                                 RakAssert(0);
00670 #endif
00671                                 // Just cancel the deletion entirely
00672                                 return;
00673                         }
00674                 }
00675 
00676                 strcpy(fullPath, applicationDirectory);
00677                 FixEndingSlash(fullPath);
00678                 strcat(fullPath, fileList[i].filename.C_String());
00679 
00680 #ifdef _MSC_VER
00681 #pragma warning( disable : 4966 ) // unlink declared deprecated by Microsoft in order to make it harder to be cross platform.  I don't agree it's deprecated.
00682 #endif
00683         int result = unlink(fullPath);
00684                 if (result!=0)
00685                 {
00686                         RAKNET_DEBUG_PRINTF("FileList::DeleteFiles: unlink (%s) failed.\n", fullPath);
00687                 }
00688         }
00689 }
00690 
00691 void FileList::SetCallback(FileListProgress *cb)
00692 {
00693         callback=cb;
00694 }
00695 
00696 bool FileList::FixEndingSlash(char *str)
00697 {
00698 #ifdef _WIN32
00699         if (str[strlen(str)-1]!='/' && str[strlen(str)-1]!='\\')
00700         {
00701                 strcat(str, "\\"); // Only \ works with system commands, used by AutopatcherClient
00702                 return true;
00703         }
00704 #else
00705         if (str[strlen(str)-1]!='\\' && str[strlen(str)-1]!='/')
00706         {
00707                 strcat(str, "/"); // Only / works with Linux
00708                 return true;
00709         }
00710 #endif
00711 
00712         return false;
00713 }
00714 
00715 #ifdef _MSC_VER
00716 #pragma warning( pop )
00717 #endif

Generated on Thu Sep 30 2010 01:27:23 for RakNet by  doxygen 1.7.1