// CreateThreadLocalTmpDir //------------------------------------------------------------------------------ /*static*/ void WorkerThread::CreateThreadLocalTmpDir() { // create isolated subdir AStackString<> tmpFileName; CreateTempFilePath( ".tmp", tmpFileName ); char * lastSlash = tmpFileName.FindLast( NATIVE_SLASH ); tmpFileName.SetLength( (uint32_t)( lastSlash - tmpFileName.Get() ) ); FileIO::EnsurePathExists( tmpFileName ); }
// Publish //------------------------------------------------------------------------------ /*virtual*/ bool Cache::Publish( const AString & cacheId, const void * data, size_t dataSize ) { AStackString<> cacheFileName; GetCacheFileName( cacheId, cacheFileName ); // make sure the cache output path exists char * lastSlash = cacheFileName.FindLast( NATIVE_SLASH ); *lastSlash = 0; if ( !FileIO::EnsurePathExists( cacheFileName ) ) { return false; } *lastSlash = NATIVE_SLASH; // open output cache (tmp) file AStackString<> cacheFileTmpName( cacheFileName ); cacheFileTmpName += ".tmp"; FileStream cacheTmpFile; if( !cacheTmpFile.Open( cacheFileTmpName.Get(), FileStream::WRITE_ONLY ) ) { return false; } // write data bool cacheTmpWriteOk = ( cacheTmpFile.Write( data, dataSize ) == dataSize ); cacheTmpFile.Close(); if ( !cacheTmpWriteOk ) { // failed to write to cache tmp file FileIO::FileDelete( cacheFileTmpName.Get() ); // try to cleanup failure return false; } // rename tmp file to real file if ( FileIO::FileMove( cacheFileTmpName, cacheFileName ) == false ) { // try to delete (possibly) existing file FileIO::FileDelete( cacheFileName.Get() ); // try rename again if ( FileIO::FileMove( cacheFileTmpName, cacheFileName ) == false ) { // problem renaming file FileIO::FileDelete( cacheFileTmpName.Get() ); // try to cleanup tmp file return false; } } return true; }
// GenerateVCXProjFilters //------------------------------------------------------------------------------ const AString & VSProjectGenerator::GenerateVCXProjFilters( const AString & projectFile ) { // preallocate to avoid re-allocations m_Tmp.SetReserved( MEGABYTE ); m_Tmp.SetLength( 0 ); // determine folder for project const char * lastProjSlash = projectFile.FindLast( NATIVE_SLASH ); AStackString<> projectBasePath( projectFile.Get(), lastProjSlash ? lastProjSlash + 1 : projectFile.Get() ); // header Write( "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" ); Write( "<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n" ); // list of all folders Array< AString > folders( 1024, true ); // files { Write( " <ItemGroup>\n" ); const AString * const fEnd = m_Files.End(); for ( const AString * fIt = m_Files.Begin(); fIt!=fEnd; ++fIt ) { // get folder part, relative to base dir AStackString<> folder; GetFolderPath( *fIt, folder ); const char * fileName = fIt->BeginsWithI( projectBasePath ) ? fIt->Get() + projectBasePath.GetLength() : fIt->Get(); Write( " <CustomBuild Include=\"%s\">\n", fileName ); if ( !folder.IsEmpty() ) { Write( " <Filter>%s</Filter>\n", folder.Get() ); } Write( " </CustomBuild>\n" ); // add new folders if ( !folder.IsEmpty() ) { for (;;) { // add this folder if unique bool found = false; for ( const AString * it=folders.Begin(); it!=folders.End(); ++it ) { if ( it->CompareI( folder ) == 0 ) { found = true; break; } } if ( !found ) { folders.Append( folder ); } // handle intermediate folders const char * lastSlash = folder.FindLast( BACK_SLASH ); if ( lastSlash == nullptr ) { break; } folder.SetLength( (uint32_t)( lastSlash - folder.Get() ) ); } } } Write( " </ItemGroup>\n" ); } // folders { const AString * const fEnd = folders.End(); for ( const AString * fIt = folders.Begin(); fIt!=fEnd; ++fIt ) { Write( " <ItemGroup>\n" ); Write( " <Filter Include=\"%s\">\n", fIt->Get() ); Write( " <UniqueIdentifier>{%08x-6c94-4f93-bc2a-7f5284b7d434}</UniqueIdentifier>\n", CRC32::Calc( *fIt ) ); Write( " </Filter>\n" ); Write( " </ItemGroup>\n" ); } } // footer Write( "</Project>" ); // no carriage return m_OutputVCXProjFilters = m_Tmp; return m_OutputVCXProjFilters; }
// ReceiveFileData //------------------------------------------------------------------------------ bool ToolManifest::ReceiveFileData( uint32_t fileId, const void * data, size_t & dataSize ) { MutexHolder mh( m_Mutex ); File & f = m_Files[ fileId ]; // gracefully handle multiple receipts of the same data if ( f.m_Content ) { ASSERT( f.m_SyncState == File::SYNCHRONIZED ); return true; } ASSERT( f.m_SyncState == File::SYNCHRONIZING ); // prepare name for this file AStackString<> fileName; GetRemoteFilePath( fileId, fileName ); // prepare destination AStackString<> pathOnly( fileName.Get(), fileName.FindLast( NATIVE_SLASH ) ); if ( !FileIO::EnsurePathExists( pathOnly ) ) { return false; // FAILED } // write to disk FileStream fs; if ( !fs.Open( fileName.Get(), FileStream::WRITE_ONLY ) ) { return false; // FAILED } if ( fs.Write( data, dataSize ) != dataSize ) { return false; // FAILED } fs.Close(); // open read-only AutoPtr< FileStream > fileStream( FNEW( FileStream ) ); if ( fileStream.Get()->Open( fileName.Get(), FileStream::READ_ONLY ) == false ) { return false; // FAILED } // This file is now synchronized f.m_FileLock = fileStream.Release(); // NOTE: Keep file open to prevent deletion f.m_SyncState = File::SYNCHRONIZED; // is completely synchronized? const File * const end = m_Files.End(); for ( const File * it = m_Files.Begin(); it != end; ++it ) { if ( it->m_SyncState != File::SYNCHRONIZED ) { // still some files to be received return true; // file stored ok } } // all files received m_Synchronized = true; return true; // file stored ok }