| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818 |
- /*
- * Copyright (c) 2014, Oculus VR, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- *
- */
- #include "FileList.h"
- #if _RAKNET_SUPPORT_FileOperations==1
- #include <stdio.h> // RAKNET_DEBUG_PRINTF
- #include "RakAssert.h"
- #if defined(ANDROID)
- #include <asm/io.h>
- #elif defined(_WIN32) || defined(__CYGWIN__)
- #include <io.h>
- #elif !defined ( __APPLE__ ) && !defined ( __APPLE_CC__ ) && !defined ( __PPC__ ) && !defined ( __FreeBSD__ ) && !defined ( __S3E__ )
- #include <sys/io.h>
- #endif
- #ifdef _WIN32
- // For mkdir
- #include <direct.h>
- #else
- #include <sys/stat.h>
- #endif
- //#include "DR_SHA1.h"
- #include "DS_Queue.h"
- #include "StringCompressor.h"
- #include "BitStream.h"
- #include "FileOperations.h"
- #include "SuperFastHash.h"
- #include "RakAssert.h"
- #include "LinuxStrings.h"
- #define MAX_FILENAME_LENGTH 512
- static const unsigned HASH_LENGTH=4;
- using namespace RakNet;
- // alloca
- #if defined(_WIN32)
- #include <malloc.h>
- #else
- #if !defined ( __FreeBSD__ )
- #include <alloca.h>
- #endif
- #include <unistd.h>
- #include <stdlib.h>
- #include <sys/stat.h>
- #include "_FindFirst.h"
- #include <stdint.h> //defines intptr_t
- #endif
- #include "RakAlloca.h"
- //int RAK_DLL_EXPORT FileListNodeComp( char * const &key, const FileListNode &data )
- //{
- // return strcmp(key, data.filename);
- //}
- STATIC_FACTORY_DEFINITIONS(FileListProgress,FileListProgress)
- STATIC_FACTORY_DEFINITIONS(FLP_Printf,FLP_Printf)
- STATIC_FACTORY_DEFINITIONS(FileList,FileList)
- #ifdef _MSC_VER
- #pragma warning( push )
- #endif
- /// First callback called when FileList::AddFilesFromDirectory() starts
- void FLP_Printf::OnAddFilesFromDirectoryStarted(FileList *fileList, char *dir) {
- (void) fileList;
- RAKNET_DEBUG_PRINTF("Adding files from directory %s\n",dir);}
- /// Called for each directory, when that directory begins processing
- void FLP_Printf::OnDirectory(FileList *fileList, char *dir, unsigned int directoriesRemaining) {
- (void) fileList;
- RAKNET_DEBUG_PRINTF("Adding %s. %i remaining.\n", dir, directoriesRemaining);}
- void FLP_Printf::OnFilePushesComplete( SystemAddress systemAddress, unsigned short setID )
- {
- (void) setID;
- char str[32];
- systemAddress.ToString(true, (char*) str);
- RAKNET_DEBUG_PRINTF("File pushes complete to %s\n", str);
- }
- void FLP_Printf::OnSendAborted( SystemAddress systemAddress )
- {
- char str[32];
- systemAddress.ToString(true, (char*) str);
- RAKNET_DEBUG_PRINTF("Send aborted to %s\n", str);
- }
- FileList::FileList()
- {
- }
- FileList::~FileList()
- {
- Clear();
- }
- void FileList::AddFile(const char *filepath, const char *filename, FileListNodeContext context)
- {
- if (filepath==0 || filename==0)
- return;
- char *data;
- //std::fstream file;
- //file.open(filename, std::ios::in | std::ios::binary);
- FILE *fp = fopen(filepath, "rb");
- if (fp==0)
- return;
- fseek(fp, 0, SEEK_END);
- int length = ftell(fp);
- fseek(fp, 0, SEEK_SET);
- if (length > (int) ((unsigned int)-1 / 8))
- {
- // 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
- RakAssert("Cannot add files over 536 MB" && 0);
- fclose(fp);
- return;
- }
- #if USE_ALLOCA==1
- bool usedAlloca=false;
- if (length < MAX_ALLOCA_STACK_ALLOCATION)
- {
- data = ( char* ) alloca( length );
- usedAlloca=true;
- }
- else
- #endif
- {
- data = (char*) rakMalloc_Ex( length, _FILE_AND_LINE_ );
- RakAssert(data);
- }
- fread(data, 1, length, fp);
- AddFile(filename, filepath, data, length, length, context);
- fclose(fp);
- #if USE_ALLOCA==1
- if (usedAlloca==false)
- #endif
- rakFree_Ex(data, _FILE_AND_LINE_ );
- }
- void FileList::AddFile(const char *filename, const char *fullPathToFile, const char *data, const unsigned dataLength, const unsigned fileLength, FileListNodeContext context, bool isAReference, bool takeDataPointer)
- {
- if (filename==0)
- return;
- if (strlen(filename)>MAX_FILENAME_LENGTH)
- {
- // Should be enough for anyone
- RakAssert(0);
- return;
- }
- // If adding a reference, do not send data
- RakAssert(isAReference==false || data==0);
- // Avoid duplicate insertions unless the data is different, in which case overwrite the old data
- unsigned i;
- for (i=0; i<fileList.Size();i++)
- {
- if (strcmp(fileList[i].filename, filename)==0)
- {
- if (fileList[i].fileLengthBytes==fileLength && fileList[i].dataLengthBytes==dataLength &&
- (dataLength==0 || fileList[i].data==0 ||
- memcmp(fileList[i].data, data, dataLength)==0
- ))
- // Exact same file already here
- return;
- // File of the same name, but different contents, so overwrite
- rakFree_Ex(fileList[i].data, _FILE_AND_LINE_ );
- fileList.RemoveAtIndex(i);
- break;
- }
- }
- FileListNode n;
- // size_t fileNameLen = strlen(filename);
- if (dataLength && data)
- {
- if (takeDataPointer)
- {
- n.data=(char*) data;
- }
- else
- {
- n.data=(char*) rakMalloc_Ex( dataLength, _FILE_AND_LINE_ );
- RakAssert(n.data);
- memcpy(n.data, data, dataLength);
- }
- }
- else
- n.data=0;
- n.dataLengthBytes=dataLength;
- n.fileLengthBytes=fileLength;
- n.isAReference=isAReference;
- n.context=context;
- if (n.context.dataPtr==0)
- n.context.dataPtr=n.data;
- if (n.context.dataLength==0)
- n.context.dataLength=dataLength;
- n.filename=filename;
- n.fullPathToFile=fullPathToFile;
-
- fileList.Insert(n, _FILE_AND_LINE_);
- }
- void FileList::AddFilesFromDirectory(const char *applicationDirectory, const char *subDirectory, bool writeHash, bool writeData, bool recursive, FileListNodeContext context)
- {
- DataStructures::Queue<char*> dirList;
- char root[260];
- char fullPath[520];
- _finddata_t fileInfo;
- intptr_t dir;
- FILE *fp;
- char *dirSoFar, *fileData;
- dirSoFar=(char*) rakMalloc_Ex( 520, _FILE_AND_LINE_ );
- RakAssert(dirSoFar);
- if (applicationDirectory)
- strcpy(root, applicationDirectory);
- else
- root[0]=0;
- int rootLen=(int)strlen(root);
- if (rootLen)
- {
- strcpy(dirSoFar, root);
- if (FixEndingSlash(dirSoFar))
- rootLen++;
- }
- else
- dirSoFar[0]=0;
-
- if (subDirectory)
- {
- strcat(dirSoFar, subDirectory);
- FixEndingSlash(dirSoFar);
- }
- for (unsigned int flpcIndex=0; flpcIndex < fileListProgressCallbacks.Size(); flpcIndex++)
- fileListProgressCallbacks[flpcIndex]->OnAddFilesFromDirectoryStarted(this, dirSoFar);
- // RAKNET_DEBUG_PRINTF("Adding files from directory %s\n",dirSoFar);
- dirList.Push(dirSoFar, _FILE_AND_LINE_ );
- while (dirList.Size())
- {
- dirSoFar=dirList.Pop();
- strcpy(fullPath, dirSoFar);
- // Changed from *.* to * for Linux compatibility
- strcat(fullPath, "*");
- dir=_findfirst(fullPath, &fileInfo );
- if (dir==-1)
- {
- _findclose(dir);
- rakFree_Ex(dirSoFar, _FILE_AND_LINE_ );
- unsigned i;
- for (i=0; i < dirList.Size(); i++)
- rakFree_Ex(dirList[i], _FILE_AND_LINE_ );
- return;
- }
- // RAKNET_DEBUG_PRINTF("Adding %s. %i remaining.\n", fullPath, dirList.Size());
- for (unsigned int flpcIndex=0; flpcIndex < fileListProgressCallbacks.Size(); flpcIndex++)
- fileListProgressCallbacks[flpcIndex]->OnDirectory(this, fullPath, dirList.Size());
- do
- {
- // no guarantee these entries are first...
- if (strcmp("." , fileInfo.name) == 0 ||
- strcmp("..", fileInfo.name) == 0)
- {
- continue;
- }
-
- if ((fileInfo.attrib & (_A_HIDDEN | _A_SUBDIR | _A_SYSTEM))==0)
- {
- strcpy(fullPath, dirSoFar);
- strcat(fullPath, fileInfo.name);
- fileData=0;
- for (unsigned int flpcIndex=0; flpcIndex < fileListProgressCallbacks.Size(); flpcIndex++)
- fileListProgressCallbacks[flpcIndex]->OnFile(this, dirSoFar, fileInfo.name, fileInfo.size);
- if (writeData && writeHash)
- {
- fp = fopen(fullPath, "rb");
- if (fp)
- {
- fileData= (char*) rakMalloc_Ex( fileInfo.size+HASH_LENGTH, _FILE_AND_LINE_ );
- RakAssert(fileData);
- fread(fileData+HASH_LENGTH, fileInfo.size, 1, fp);
- fclose(fp);
- unsigned int hash = SuperFastHash(fileData+HASH_LENGTH, fileInfo.size);
- if (RakNet::BitStream::DoEndianSwap())
- RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &hash, sizeof(hash));
- memcpy(fileData, &hash, HASH_LENGTH);
- // sha1.Reset();
- // sha1.Update( ( unsigned char* ) fileData+HASH_LENGTH, fileInfo.size );
- // sha1.Final();
- // memcpy(fileData, sha1.GetHash(), HASH_LENGTH);
- // File data and hash
- AddFile((const char*)fullPath+rootLen, fullPath, fileData, fileInfo.size+HASH_LENGTH, fileInfo.size, context);
- }
- }
- else if (writeHash)
- {
- // sha1.Reset();
- // DR_SHA1.hashFile((char*)fullPath);
- // sha1.Final();
- unsigned int hash = SuperFastHashFile(fullPath);
- if (RakNet::BitStream::DoEndianSwap())
- RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &hash, sizeof(hash));
- // Hash only
- // AddFile((const char*)fullPath+rootLen, (const char*)sha1.GetHash(), HASH_LENGTH, fileInfo.size, context);
- AddFile((const char*)fullPath+rootLen, fullPath, (const char*)&hash, HASH_LENGTH, fileInfo.size, context);
- }
- else if (writeData)
- {
- fileData= (char*) rakMalloc_Ex( fileInfo.size, _FILE_AND_LINE_ );
- RakAssert(fileData);
- fp = fopen(fullPath, "rb");
- fread(fileData, fileInfo.size, 1, fp);
- fclose(fp);
- // File data only
- AddFile(fullPath+rootLen, fullPath, fileData, fileInfo.size, fileInfo.size, context);
- }
- else
- {
- // Just the filename
- AddFile(fullPath+rootLen, fullPath, 0, 0, fileInfo.size, context);
- }
- if (fileData)
- rakFree_Ex(fileData, _FILE_AND_LINE_ );
- }
- else if ((fileInfo.attrib & _A_SUBDIR) && (fileInfo.attrib & (_A_HIDDEN | _A_SYSTEM))==0 && recursive)
- {
- char *newDir=(char*) rakMalloc_Ex( 520, _FILE_AND_LINE_ );
- RakAssert(newDir);
- strcpy(newDir, dirSoFar);
- strcat(newDir, fileInfo.name);
- strcat(newDir, "/");
- dirList.Push(newDir, _FILE_AND_LINE_ );
- }
- } while (_findnext(dir, &fileInfo ) != -1);
- _findclose(dir);
- rakFree_Ex(dirSoFar, _FILE_AND_LINE_ );
- }
- }
- void FileList::Clear(void)
- {
- unsigned i;
- for (i=0; i<fileList.Size(); i++)
- {
- rakFree_Ex(fileList[i].data, _FILE_AND_LINE_ );
- }
- fileList.Clear(false, _FILE_AND_LINE_);
- }
- void FileList::Serialize(RakNet::BitStream *outBitStream)
- {
- outBitStream->WriteCompressed(fileList.Size());
- unsigned i;
- for (i=0; i < fileList.Size(); i++)
- {
- outBitStream->WriteCompressed(fileList[i].context.op);
- outBitStream->WriteCompressed(fileList[i].context.flnc_extraData1);
- outBitStream->WriteCompressed(fileList[i].context.flnc_extraData2);
- StringCompressor::Instance()->EncodeString(fileList[i].filename.C_String(), MAX_FILENAME_LENGTH, outBitStream);
- bool writeFileData = (fileList[i].dataLengthBytes>0)==true;
- outBitStream->Write(writeFileData);
- if (writeFileData)
- {
- outBitStream->WriteCompressed(fileList[i].dataLengthBytes);
- outBitStream->Write(fileList[i].data, fileList[i].dataLengthBytes);
- }
- outBitStream->Write((bool)(fileList[i].fileLengthBytes==fileList[i].dataLengthBytes));
- if (fileList[i].fileLengthBytes!=fileList[i].dataLengthBytes)
- outBitStream->WriteCompressed(fileList[i].fileLengthBytes);
- }
- }
- bool FileList::Deserialize(RakNet::BitStream *inBitStream)
- {
- bool b, dataLenNonZero=false, fileLenMatchesDataLen=false;
- char filename[512];
- uint32_t fileListSize;
- FileListNode n;
- b=inBitStream->ReadCompressed(fileListSize);
- #ifdef _DEBUG
- RakAssert(b);
- RakAssert(fileListSize < 10000);
- #endif
- if (b==false || fileListSize > 10000)
- return false; // Sanity check
- Clear();
- unsigned i;
- for (i=0; i < fileListSize; i++)
- {
- inBitStream->ReadCompressed(n.context.op);
- inBitStream->ReadCompressed(n.context.flnc_extraData1);
- inBitStream->ReadCompressed(n.context.flnc_extraData2);
- StringCompressor::Instance()->DecodeString((char*)filename, MAX_FILENAME_LENGTH, inBitStream);
- inBitStream->Read(dataLenNonZero);
- if (dataLenNonZero)
- {
- inBitStream->ReadCompressed(n.dataLengthBytes);
- // sanity check
- if (n.dataLengthBytes>2000000000)
- {
- #ifdef _DEBUG
- RakAssert(n.dataLengthBytes<=2000000000);
- #endif
- return false;
- }
- n.data=(char*) rakMalloc_Ex( (size_t) n.dataLengthBytes, _FILE_AND_LINE_ );
- RakAssert(n.data);
- inBitStream->Read(n.data, n.dataLengthBytes);
- }
- else
- {
- n.dataLengthBytes=0;
- n.data=0;
- }
-
- b=inBitStream->Read(fileLenMatchesDataLen);
- if (fileLenMatchesDataLen)
- n.fileLengthBytes=(unsigned) n.dataLengthBytes;
- else
- b=inBitStream->ReadCompressed(n.fileLengthBytes);
- #ifdef _DEBUG
- RakAssert(b);
- #endif
- if (b==0)
- {
- Clear();
- return false;
- }
- n.filename=filename;
- n.fullPathToFile=filename;
- fileList.Insert(n, _FILE_AND_LINE_);
- }
- return true;
- }
- void FileList::GetDeltaToCurrent(FileList *input, FileList *output, const char *dirSubset, const char *remoteSubdir)
- {
- // For all files in this list that do not match the input list, write them to the output list.
- // dirSubset allows checking only a portion of the files in this list.
- unsigned thisIndex, inputIndex;
- unsigned dirSubsetLen, localPathLen, remoteSubdirLen;
- bool match;
- if (dirSubset)
- dirSubsetLen = (unsigned int) strlen(dirSubset);
- else
- dirSubsetLen = 0;
- if (remoteSubdir && remoteSubdir[0])
- {
- remoteSubdirLen=(unsigned int) strlen(remoteSubdir);
- if (IsSlash(remoteSubdir[remoteSubdirLen-1]))
- remoteSubdirLen--;
- }
- else
- remoteSubdirLen=0;
- for (thisIndex=0; thisIndex < fileList.Size(); thisIndex++)
- {
- localPathLen = (unsigned int) fileList[thisIndex].filename.GetLength();
- while (localPathLen>0)
- {
- if (IsSlash(fileList[thisIndex].filename[localPathLen-1]))
- {
- localPathLen--;
- break;
- }
- localPathLen--;
- }
- // fileList[thisIndex].filename has to match dirSubset and be shorter or equal to it in length.
- if (dirSubsetLen>0 &&
- (localPathLen<dirSubsetLen ||
- _strnicmp(fileList[thisIndex].filename.C_String(), dirSubset, dirSubsetLen)!=0 ||
- (localPathLen>dirSubsetLen && IsSlash(fileList[thisIndex].filename[dirSubsetLen])==false)))
- continue;
- match=false;
- for (inputIndex=0; inputIndex < input->fileList.Size(); inputIndex++)
- {
- // If the filenames, hashes, and lengths match then skip this element in fileList. Otherwise write it to output
- if (_stricmp(input->fileList[inputIndex].filename.C_String()+remoteSubdirLen,fileList[thisIndex].filename.C_String()+dirSubsetLen)==0)
- {
- match=true;
- if (input->fileList[inputIndex].fileLengthBytes==fileList[thisIndex].fileLengthBytes &&
- input->fileList[inputIndex].dataLengthBytes==fileList[thisIndex].dataLengthBytes &&
- memcmp(input->fileList[inputIndex].data,fileList[thisIndex].data,(size_t) fileList[thisIndex].dataLengthBytes)==0)
- {
- // File exists on both machines and is the same.
- break;
- }
- else
- {
- // File exists on both machines and is not the same.
- output->AddFile(fileList[thisIndex].filename, fileList[thisIndex].fullPathToFile, 0,0, fileList[thisIndex].fileLengthBytes, FileListNodeContext(0,0,0,0), false);
- break;
- }
- }
- }
- if (match==false)
- {
- // Other system does not have the file at all
- output->AddFile(fileList[thisIndex].filename, fileList[thisIndex].fullPathToFile, 0,0, fileList[thisIndex].fileLengthBytes, FileListNodeContext(0,0,0,0), false);
- }
- }
- }
- void FileList::ListMissingOrChangedFiles(const char *applicationDirectory, FileList *missingOrChangedFiles, bool alwaysWriteHash, bool neverWriteHash)
- {
- unsigned fileLength;
- // CSHA1 sha1;
- FILE *fp;
- char fullPath[512];
- unsigned i;
- // char *fileData;
- for (i=0; i < fileList.Size(); i++)
- {
- strcpy(fullPath, applicationDirectory);
- FixEndingSlash(fullPath);
- strcat(fullPath,fileList[i].filename);
- fp=fopen(fullPath, "rb");
- if (fp==0)
- {
- missingOrChangedFiles->AddFile(fileList[i].filename, fileList[i].fullPathToFile, 0, 0, 0, FileListNodeContext(0,0,0,0), false);
- }
- else
- {
- fseek(fp, 0, SEEK_END);
- fileLength = ftell(fp);
- fseek(fp, 0, SEEK_SET);
- if (fileLength != fileList[i].fileLengthBytes && alwaysWriteHash==false)
- {
- missingOrChangedFiles->AddFile(fileList[i].filename, fileList[i].fullPathToFile, 0, 0, fileLength, FileListNodeContext(0,0,0,0), false);
- }
- else
- {
- // fileData= (char*) rakMalloc_Ex( fileLength, _FILE_AND_LINE_ );
- // fread(fileData, fileLength, 1, fp);
- // sha1.Reset();
- // sha1.Update( ( unsigned char* ) fileData, fileLength );
- // sha1.Final();
- // rakFree_Ex(fileData, _FILE_AND_LINE_ );
- unsigned int hash = SuperFastHashFilePtr(fp);
- if (RakNet::BitStream::DoEndianSwap())
- RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &hash, sizeof(hash));
- //if (fileLength != fileList[i].fileLength || memcmp( sha1.GetHash(), fileList[i].data, HASH_LENGTH)!=0)
- if (fileLength != fileList[i].fileLengthBytes || memcmp( &hash, fileList[i].data, HASH_LENGTH)!=0)
- {
- if (neverWriteHash==false)
- // missingOrChangedFiles->AddFile((const char*)fileList[i].filename, (const char*)sha1.GetHash(), HASH_LENGTH, fileLength, 0);
- missingOrChangedFiles->AddFile((const char*)fileList[i].filename, (const char*)fileList[i].fullPathToFile, (const char *) &hash, HASH_LENGTH, fileLength, FileListNodeContext(0,0,0,0), false);
- else
- missingOrChangedFiles->AddFile((const char*)fileList[i].filename, (const char*)fileList[i].fullPathToFile, 0, 0, fileLength, FileListNodeContext(0,0,0,0), false);
- }
- }
- fclose(fp);
- }
- }
- }
- void FileList::PopulateDataFromDisk(const char *applicationDirectory, bool writeFileData, bool writeFileHash, bool removeUnknownFiles)
- {
- FILE *fp;
- char fullPath[512];
- unsigned i;
- // CSHA1 sha1;
- i=0;
- while (i < fileList.Size())
- {
- rakFree_Ex(fileList[i].data, _FILE_AND_LINE_ );
- strcpy(fullPath, applicationDirectory);
- FixEndingSlash(fullPath);
- strcat(fullPath,fileList[i].filename.C_String());
- fp=fopen(fullPath, "rb");
- if (fp)
- {
- if (writeFileHash || writeFileData)
- {
- fseek(fp, 0, SEEK_END);
- fileList[i].fileLengthBytes = ftell(fp);
- fseek(fp, 0, SEEK_SET);
- if (writeFileHash)
- {
- if (writeFileData)
- {
- // Hash + data so offset the data by HASH_LENGTH
- fileList[i].data=(char*) rakMalloc_Ex( fileList[i].fileLengthBytes+HASH_LENGTH, _FILE_AND_LINE_ );
- RakAssert(fileList[i].data);
- fread(fileList[i].data+HASH_LENGTH, fileList[i].fileLengthBytes, 1, fp);
- // sha1.Reset();
- // sha1.Update((unsigned char*)fileList[i].data+HASH_LENGTH, fileList[i].fileLength);
- // sha1.Final();
- unsigned int hash = SuperFastHash(fileList[i].data+HASH_LENGTH, fileList[i].fileLengthBytes);
- if (RakNet::BitStream::DoEndianSwap())
- RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &hash, sizeof(hash));
- // memcpy(fileList[i].data, sha1.GetHash(), HASH_LENGTH);
- memcpy(fileList[i].data, &hash, HASH_LENGTH);
- }
- else
- {
- // Hash only
- fileList[i].dataLengthBytes=HASH_LENGTH;
- if (fileList[i].fileLengthBytes < HASH_LENGTH)
- fileList[i].data=(char*) rakMalloc_Ex( HASH_LENGTH, _FILE_AND_LINE_ );
- else
- fileList[i].data=(char*) rakMalloc_Ex( fileList[i].fileLengthBytes, _FILE_AND_LINE_ );
- RakAssert(fileList[i].data);
- fread(fileList[i].data, fileList[i].fileLengthBytes, 1, fp);
- // sha1.Reset();
- // sha1.Update((unsigned char*)fileList[i].data, fileList[i].fileLength);
- // sha1.Final();
- unsigned int hash = SuperFastHash(fileList[i].data, fileList[i].fileLengthBytes);
- if (RakNet::BitStream::DoEndianSwap())
- RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &hash, sizeof(hash));
- // memcpy(fileList[i].data, sha1.GetHash(), HASH_LENGTH);
- memcpy(fileList[i].data, &hash, HASH_LENGTH);
- }
- }
- else
- {
- // Data only
- fileList[i].dataLengthBytes=fileList[i].fileLengthBytes;
- fileList[i].data=(char*) rakMalloc_Ex( fileList[i].fileLengthBytes, _FILE_AND_LINE_ );
- RakAssert(fileList[i].data);
- fread(fileList[i].data, fileList[i].fileLengthBytes, 1, fp);
- }
- fclose(fp);
- i++;
- }
- else
- {
- fileList[i].data=0;
- fileList[i].dataLengthBytes=0;
- }
- }
- else
- {
- if (removeUnknownFiles)
- {
- fileList.RemoveAtIndex(i);
- }
- else
- i++;
- }
- }
- }
- void FileList::FlagFilesAsReferences(void)
- {
- for (unsigned int i=0; i < fileList.Size(); i++)
- {
- fileList[i].isAReference=true;
- fileList[i].dataLengthBytes=fileList[i].fileLengthBytes;
- }
- }
- void FileList::WriteDataToDisk(const char *applicationDirectory)
- {
- char fullPath[512];
- unsigned i,j;
- for (i=0; i < fileList.Size(); i++)
- {
- strcpy(fullPath, applicationDirectory);
- FixEndingSlash(fullPath);
- strcat(fullPath,fileList[i].filename.C_String());
-
- // Security - Don't allow .. in the filename anywhere so you can't write outside of the root directory
- for (j=1; j < fileList[i].filename.GetLength(); j++)
- {
- if (fileList[i].filename[j]=='.' && fileList[i].filename[j-1]=='.')
- {
- #ifdef _DEBUG
- RakAssert(0);
- #endif
- // Just cancel the write entirely
- return;
- }
- }
- WriteFileWithDirectories(fullPath, fileList[i].data, (unsigned int) fileList[i].dataLengthBytes);
- }
- }
- #ifdef _MSC_VER
- #pragma warning( disable : 4996 ) // unlink declared deprecated by Microsoft in order to make it harder to be cross platform. I don't agree it's deprecated.
- #endif
- void FileList::DeleteFiles(const char *applicationDirectory)
- {
- char fullPath[512];
- unsigned i,j;
- for (i=0; i < fileList.Size(); i++)
- {
- // The filename should not have .. in the path - if it does ignore it
- for (j=1; j < fileList[i].filename.GetLength(); j++)
- {
- if (fileList[i].filename[j]=='.' && fileList[i].filename[j-1]=='.')
- {
- #ifdef _DEBUG
- RakAssert(0);
- #endif
- // Just cancel the deletion entirely
- return;
- }
- }
- strcpy(fullPath, applicationDirectory);
- FixEndingSlash(fullPath);
- strcat(fullPath, fileList[i].filename.C_String());
-
- // Do not rename to _unlink as linux uses unlink
- #if defined(WINDOWS_PHONE_8) || defined(WINDOWS_STORE_RT)
- int result = _unlink(fullPath);
- #else
- int result = unlink(fullPath);
- #endif
- if (result!=0)
- {
- RAKNET_DEBUG_PRINTF("FileList::DeleteFiles: unlink (%s) failed.\n", fullPath);
- }
- }
- }
- void FileList::AddCallback(FileListProgress *cb)
- {
- if (cb==0)
- return;
- if ((unsigned int) fileListProgressCallbacks.GetIndexOf(cb)==(unsigned int)-1)
- fileListProgressCallbacks.Push(cb, _FILE_AND_LINE_);
- }
- void FileList::RemoveCallback(FileListProgress *cb)
- {
- unsigned int idx = fileListProgressCallbacks.GetIndexOf(cb);
- if (idx!=(unsigned int) -1)
- fileListProgressCallbacks.RemoveAtIndex(idx);
- }
- void FileList::ClearCallbacks(void)
- {
- fileListProgressCallbacks.Clear(true, _FILE_AND_LINE_);
- }
- void FileList::GetCallbacks(DataStructures::List<FileListProgress*> &callbacks)
- {
- callbacks = fileListProgressCallbacks;
- }
- bool FileList::FixEndingSlash(char *str)
- {
- #ifdef _WIN32
- if (str[strlen(str)-1]!='/' && str[strlen(str)-1]!='\\')
- {
- strcat(str, "\\"); // Only \ works with system commands, used by AutopatcherClient
- return true;
- }
- #else
- if (str[strlen(str)-1]!='\\' && str[strlen(str)-1]!='/')
- {
- strcat(str, "/"); // Only / works with Linux
- return true;
- }
- #endif
- return false;
- }
- #ifdef _MSC_VER
- #pragma warning( pop )
- #endif
- #endif // _RAKNET_SUPPORT_FileOperations
|