void startBackup(COptions options) { GUID snapshotSetId = GUID_NULL; bool bSnapshotCreated = false; bool bAbnormalAbort = true; CComPtr<IVssBackupComponents> pBackupComponents; int fileCount = 0; LONGLONG byteCount = 0; int directoryCount = 0; int skipCount = 0; SYSTEMTIME startTime; try { OutputWriter::SetVerbosityLevel((VERBOSITY_LEVEL)options.get_VerbosityLevel()); //for (int i = 0; i < argc; ++i) //{ // CString message; // message.AppendFormat(TEXT("Argument %d: %s"), i, argv[i]); // OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_IF_VERBOSE); //} OutputWriter::WriteLine(TEXT("Calling CoInitialize")); CHECK_HRESULT(::CoInitialize(NULL)); CHECK_HRESULT( ::CoInitializeSecurity( NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IDENTIFY, NULL, EOAC_NONE, NULL)); ::GetSystemTime(&startTime); CString startTimeString; Utilities::FormatDateTime(&startTime, TEXT(" "), false, startTimeString); CString message; message.AppendFormat(TEXT("Starting a %s copy from %s to %s"), options.get_BackupType() == VSS_BT_FULL ? TEXT("full") : TEXT("incremental"), options.get_Source(), options.get_Destination()); OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_NORMAL); if (options.get_ClearDestination()) { if (!Utilities::DirectoryExists(options.get_Destination())) { CString message; message.AppendFormat(TEXT("Skipping recursive delete of destination directory %s because it appears not to exist."), options.get_Destination()); OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_NORMAL); } else { CString message; message.AppendFormat(TEXT("Recursively deleting destination directory %s."), options.get_Destination()); OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_NORMAL); bool doDelete = options.get_AcceptAll(); if (!doDelete) { if (Confirm(message)) { doDelete = true; } else { OutputWriter::WriteLine(TEXT("Aborting backup."), VERBOSITY_THRESHOLD_NORMAL); return; } } if (doDelete) { DeleteRecursive(options.get_Destination(), options.get_IgnorePattern()); } } } CBackupState backupState; LPSYSTEMTIME lastBackupTime; if (options.get_BackupType() == VSS_BT_INCREMENTAL) { backupState.Load(options.get_StateFile()); LPSYSTEMTIME lastFullBackupTime = backupState.get_LastFullBackupTime(); LPSYSTEMTIME lastIncrementalBackupTime = backupState.get_LastIncrementalBackupTime(); if (lastIncrementalBackupTime != NULL) { lastBackupTime = lastIncrementalBackupTime; } else { lastBackupTime = lastFullBackupTime; } } OutputWriter::WriteLine(TEXT("Calling CreateVssBackupComponents")); CHECK_HRESULT(::CreateVssBackupComponents(&pBackupComponents)); OutputWriter::WriteLine(TEXT("Calling InitializeForBackup")); CHECK_HRESULT(pBackupComponents->InitializeForBackup()); CComPtr<IVssAsync> pWriterMetadataStatus; OutputWriter::WriteLine(TEXT("Calling GatherWriterMetadata")); CHECK_HRESULT(pBackupComponents->GatherWriterMetadata(&pWriterMetadataStatus)); OutputWriter::WriteLine(TEXT("Waiting for call to GatherWriterMetadata to finish...")); CHECK_HRESULT(pWriterMetadataStatus->Wait()); HRESULT hrGatherStatus; OutputWriter::WriteLine(TEXT("Calling QueryStatus for GatherWriterMetadata")); CHECK_HRESULT(pWriterMetadataStatus->QueryStatus(&hrGatherStatus, NULL)); if (hrGatherStatus == VSS_S_ASYNC_CANCELLED) { throw new CVSSCopyException(L"GatherWriterMetadata was cancelled."); } OutputWriter::WriteLine(TEXT("Call to GatherWriterMetadata finished.")); OutputWriter::WriteLine(TEXT("Calling GetWriterMetadataCount")); vector<CWriter> writers; UINT cWriters; CHECK_HRESULT(pBackupComponents->GetWriterMetadataCount(&cWriters)); for (UINT iWriter = 0; iWriter < cWriters; ++iWriter) { CWriter writer; CComPtr<IVssExamineWriterMetadata> pExamineWriterMetadata; GUID id; OutputWriter::WriteLine(TEXT("Calling GetWriterMetadata")); CHECK_HRESULT(pBackupComponents->GetWriterMetadata(iWriter, &id, &pExamineWriterMetadata)); GUID idInstance; GUID idWriter; BSTR bstrWriterName; VSS_USAGE_TYPE usage; VSS_SOURCE_TYPE source; CHECK_HRESULT(pExamineWriterMetadata->GetIdentity(&idInstance, &idWriter, &bstrWriterName, &usage, &source)); writer.set_InstanceId(idInstance); writer.set_Name(bstrWriterName); writer.set_WriterId(idWriter); CComBSTR writerName(bstrWriterName); CString message; message.AppendFormat(TEXT("Writer %d named %s"), iWriter, (LPCTSTR)writerName); OutputWriter::WriteLine(message); UINT cIncludeFiles; UINT cExcludeFiles; UINT cComponents; CHECK_HRESULT(pExamineWriterMetadata->GetFileCounts(&cIncludeFiles, &cExcludeFiles, &cComponents)); message.Empty(); message.AppendFormat(TEXT("Writer has %d components"), cComponents); OutputWriter::WriteLine(message); for (UINT iComponent = 0; iComponent < cComponents; ++iComponent) { CWriterComponent component; CComPtr<IVssWMComponent> pComponent; CHECK_HRESULT(pExamineWriterMetadata->GetComponent(iComponent, &pComponent)); PVSSCOMPONENTINFO pComponentInfo; CHECK_HRESULT(pComponent->GetComponentInfo(&pComponentInfo)); CString message; message.AppendFormat(TEXT("Component %d is named %s, has a path of %s, and is %sselectable for backup. %d files, %d databases, %d log files."), iComponent, pComponentInfo->bstrComponentName, pComponentInfo->bstrLogicalPath, pComponentInfo->bSelectable ? TEXT("") : TEXT("not "), pComponentInfo->cFileCount, pComponentInfo->cDatabases, pComponentInfo->cLogFiles); OutputWriter::WriteLine(message); component.set_LogicalPath(pComponentInfo->bstrLogicalPath); component.set_SelectableForBackup(pComponentInfo->bSelectable); component.set_Writer(iWriter); component.set_Name(pComponentInfo->bstrComponentName); component.set_Type(pComponentInfo->type); for (UINT iFile = 0; iFile < pComponentInfo->cFileCount; ++iFile) { CComPtr<IVssWMFiledesc> pFileDesc; CHECK_HRESULT(pComponent->GetFile(iFile, &pFileDesc)); CComBSTR bstrPath; CHECK_HRESULT(pFileDesc->GetPath(&bstrPath)); CComBSTR bstrFileSpec; CHECK_HRESULT(pFileDesc->GetFilespec(&bstrFileSpec)); CString message; message.AppendFormat(TEXT("File %d has path %s\\%s"), iFile, bstrPath, bstrFileSpec); OutputWriter::WriteLine(message); } for (UINT iDatabase = 0; iDatabase < pComponentInfo->cDatabases; ++iDatabase) { CComPtr<IVssWMFiledesc> pFileDesc; CHECK_HRESULT(pComponent->GetDatabaseFile(iDatabase, &pFileDesc)); CComBSTR bstrPath; CHECK_HRESULT(pFileDesc->GetPath(&bstrPath)); CComBSTR bstrFileSpec; CHECK_HRESULT(pFileDesc->GetFilespec(&bstrFileSpec)); CString message; message.AppendFormat(TEXT("Database file %d has path %s\\%s"), iDatabase, bstrPath, bstrFileSpec); OutputWriter::WriteLine(message); } for (UINT iDatabaseLogFile = 0; iDatabaseLogFile < pComponentInfo->cLogFiles; ++iDatabaseLogFile) { CComPtr<IVssWMFiledesc> pFileDesc; CHECK_HRESULT(pComponent->GetDatabaseLogFile(iDatabaseLogFile, &pFileDesc)); CComBSTR bstrPath; CHECK_HRESULT(pFileDesc->GetPath(&bstrPath)); CComBSTR bstrFileSpec; CHECK_HRESULT(pFileDesc->GetFilespec(&bstrFileSpec)); CString message; message.AppendFormat(TEXT("Database log file %d has path %s\\%s"), iDatabaseLogFile, bstrPath, bstrFileSpec); OutputWriter::WriteLine(message); } CHECK_HRESULT(pComponent->FreeComponentInfo(pComponentInfo)); writer.get_Components().push_back(component); } writer.ComputeComponentTree(); for (unsigned int iComponent = 0; iComponent < writer.get_Components().size(); ++iComponent) { CWriterComponent& component = writer.get_Components()[iComponent]; CString message; message.AppendFormat(TEXT("Component %d has name %s, path %s, is %sselectable for backup, and has parent %s"), iComponent, component.get_Name(), component.get_LogicalPath(), component.get_SelectableForBackup() ? TEXT("") : TEXT("not "), component.get_Parent() == NULL ? TEXT("(no parent)") : component.get_Parent()->get_Name()); OutputWriter::WriteLine(message); } writers.push_back(writer); } OutputWriter::WriteLine(TEXT("Calling StartSnapshotSet")); CHECK_HRESULT(pBackupComponents->StartSnapshotSet(&snapshotSetId)); OutputWriter::WriteLine(TEXT("Calling GetVolumePathName")); WCHAR wszVolumePathName[MAX_PATH]; BOOL bWorked = ::GetVolumePathName(options.get_Source(), wszVolumePathName, MAX_PATH); if (!bWorked) { DWORD error = ::GetLastError(); CString errorMessage; Utilities::FormatErrorMessage(error, errorMessage); CString message; message.AppendFormat(TEXT("There was an error retrieving the volume name from the path. Path: %s Error: %s"), options.get_Source(), errorMessage); throw new CVSSCopyException(message.GetString()); } OutputWriter::WriteLine(TEXT("Calling AddToSnapshotSet")); GUID snapshotId; CHECK_HRESULT(pBackupComponents->AddToSnapshotSet(wszVolumePathName, GUID_NULL, &snapshotId)); for (unsigned int iWriter = 0; iWriter < writers.size(); ++iWriter) { CWriter writer = writers[iWriter]; CString message; message.AppendFormat(TEXT("Adding components to snapshot set for writer %s"), writer.get_Name()); OutputWriter::WriteLine(message); for (unsigned int iComponent = 0; iComponent < writer.get_Components().size(); ++iComponent) { CWriterComponent component = writer.get_Components()[iComponent]; if (ShouldAddComponent(component)) { CString message; message.AppendFormat(TEXT("Adding component %s (%s) from writer %s"), component.get_Name(), component.get_LogicalPath(), writer.get_Name()); OutputWriter::WriteLine(message); CHECK_HRESULT(pBackupComponents->AddComponent( writer.get_InstanceId(), writer.get_WriterId(), component.get_Type(), component.get_LogicalPath(), component.get_Name() )); } else { CString message; message.AppendFormat(TEXT("Not adding component %s from writer %s."), component.get_Name(), writer.get_Name()); OutputWriter::WriteLine(message); } } } OutputWriter::WriteLine(TEXT("Calling SetBackupState")); // Issue #29: trying to figure out if using VSS_BT_INCREMENTAL causes a problem CHECK_HRESULT(pBackupComponents->SetBackupState(TRUE, FALSE, VSS_BT_FULL, FALSE)); OutputWriter::WriteLine(TEXT("Calling PrepareForBackup")); CComPtr<IVssAsync> pPrepareForBackupResults; CHECK_HRESULT(pBackupComponents->PrepareForBackup(&pPrepareForBackupResults)); OutputWriter::WriteLine(TEXT("Waiting for call to PrepareForBackup to finish...")); CHECK_HRESULT(pPrepareForBackupResults->Wait()); HRESULT hrPrepareForBackupResults; CHECK_HRESULT(pPrepareForBackupResults->QueryStatus(&hrPrepareForBackupResults, NULL)); if (hrPrepareForBackupResults != VSS_S_ASYNC_FINISHED) { throw new CVSSCopyException(TEXT("Prepare for backup failed.")); } OutputWriter::WriteLine(TEXT("Call to PrepareForBackup finished.")); SYSTEMTIME snapshotTime; ::GetSystemTime(&snapshotTime); bWorked = ::SetConsoleCtrlHandler(CtrlHandler, TRUE); if (!bWorked) { OutputWriter::WriteLine(TEXT("Unable to set control handler. Ctrl-C and Ctrl-Break may have undesirable results."), VERBOSITY_THRESHOLD_NORMAL); } if (!options.get_Simulate()) { OutputWriter::WriteLine(TEXT("Calling DoSnapshotSet")); CComPtr<IVssAsync> pDoSnapshotSetResults; CHECK_HRESULT(pBackupComponents->DoSnapshotSet(&pDoSnapshotSetResults)); OutputWriter::WriteLine(TEXT("Waiting for call to DoSnapshotSet to finish...")); CHECK_HRESULT(pDoSnapshotSetResults->Wait()); bSnapshotCreated = true; if (s_cancel) { throw new CVSSCopyException(TEXT("Processing was cancelled by control-c, control-break, or a shutdown event. Terminating.")); } bWorked = ::SetConsoleCtrlHandler(CtrlHandler, FALSE); if (!bWorked) { OutputWriter::WriteLine(TEXT("Unable to reset control handler. Ctrl-C and Ctrl-Break may have undesirable results."), VERBOSITY_THRESHOLD_NORMAL); } HRESULT hrDoSnapshotSetResults; CHECK_HRESULT(pDoSnapshotSetResults->QueryStatus(&hrDoSnapshotSetResults, NULL)); if (hrDoSnapshotSetResults != VSS_S_ASYNC_FINISHED) { throw new CVSSCopyException(L"DoSnapshotSet failed."); } OutputWriter::WriteLine(TEXT("Call to DoSnapshotSet finished.")); OutputWriter::WriteLine(TEXT("Calling GetSnapshotProperties")); VSS_SNAPSHOT_PROP snapshotProperties; CHECK_HRESULT(pBackupComponents->GetSnapshotProperties(snapshotId, &snapshotProperties)); OutputWriter::WriteLine(TEXT("Calling CalculateSourcePath")); // TODO: We'll eventually have to deal with mount points CString wszSource; CalculateSourcePath( snapshotProperties.m_pwszSnapshotDeviceObject, options.get_Source(), wszVolumePathName, wszSource ); message.Empty(); message.AppendFormat(TEXT("Recursively creating destination directory %s."), options.get_Destination()); OutputWriter::WriteLine(message); Utilities::CreateDirectory(options.get_Destination()); OutputWriter::WriteLine(TEXT("Calling CopyRecursive")); vector<CCopyFilter*> filters; if (options.get_BackupType() == VSS_BT_FULL) { filters.push_back(new CIncludeAllCopyFilter()); } else if (options.get_BackupType() == VSS_BT_INCREMENTAL) { filters.push_back(new CModifiedSinceCopyFilter(lastBackupTime, options.get_SkipDenied())); } filters.push_back(new CFilespecCopyFilter(options.get_Filespecs())); CCopyAction copyAction(wszSource, options.get_Destination(), options.get_SkipDenied(), filters); ProcessDirectory(wszSource, copyAction, TEXT(""), options.get_Recursive(), options.get_IgnorePattern()); for (unsigned int iFilter = 0; iFilter < filters.size(); ++iFilter) { delete filters[iFilter]; } fileCount = copyAction.get_FileCount(); directoryCount = copyAction.get_DirectoryCount(); skipCount = copyAction.get_SkipCount(); byteCount = copyAction.get_ByteCount(); OutputWriter::WriteLine(TEXT("Calling BackupComplete")); CComPtr<IVssAsync> pBackupCompleteResults; CHECK_HRESULT(pBackupComponents->BackupComplete(&pBackupCompleteResults)); OutputWriter::WriteLine(TEXT("Waiting for call to BackupComplete to finish...")); CHECK_HRESULT(pBackupCompleteResults->Wait()); HRESULT hrBackupCompleteResults; CHECK_HRESULT(pBackupCompleteResults->QueryStatus(&hrBackupCompleteResults, NULL)); if (hrBackupCompleteResults != VSS_S_ASYNC_FINISHED) { throw new CVSSCopyException(TEXT("Completion of backup failed.")); } OutputWriter::WriteLine(TEXT("Call to BackupComplete finished.")); bAbnormalAbort = false; if (options.get_StateFile() != NULL) { OutputWriter::WriteLine(TEXT("Calling SaveAsXML")); CComBSTR bstrBackupDocument; CHECK_HRESULT(pBackupComponents->SaveAsXML(&bstrBackupDocument)); if (options.get_BackupType() == VSS_BT_FULL) { backupState.set_LastFullBackupTime(&snapshotTime); } else if (options.get_BackupType() == VSS_BT_INCREMENTAL) { backupState.set_LastIncrementalBackupTime(&snapshotTime); } else { throw new CVSSCopyException(TEXT("Unsupported backup type.")); } backupState.Save(options.get_StateFile(), bstrBackupDocument); } } } catch (CComException* e) { Cleanup(bAbnormalAbort, bSnapshotCreated, pBackupComponents, snapshotSetId); CString message; CString file; e->get_File(file); message.Format(TEXT("There was a COM failure 0x%x - %s (%d)"), e->get_Hresult(), file, e->get_Line()); OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_UNLESS_SILENT); return; } catch (CVSSCopyException* e) { Cleanup(bAbnormalAbort, bSnapshotCreated, pBackupComponents, snapshotSetId); OutputWriter::WriteLine(e->get_Message(), VERBOSITY_THRESHOLD_UNLESS_SILENT); return; } catch (CParseOptionsException* e) { Cleanup(bAbnormalAbort, bSnapshotCreated, pBackupComponents, snapshotSetId); CString message; message.AppendFormat(TEXT("Error: %s\n"), e->get_Message()); OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_UNLESS_SILENT); OutputWriter::WriteLine(COptions::get_Usage(), VERBOSITY_THRESHOLD_UNLESS_SILENT); return; } Cleanup(false, bSnapshotCreated, pBackupComponents, snapshotSetId); OutputWriter::WriteLine(TEXT("Backup successfully completed."), VERBOSITY_THRESHOLD_UNLESS_SILENT); CString message; CString startTimeStringLocal; Utilities::FormatDateTime(&startTime, TEXT(" "), true, startTimeStringLocal); CString finishTimeString; SYSTEMTIME finishTime; ::GetSystemTime(&finishTime); Utilities::FormatDateTime(&finishTime, TEXT(" "), true, finishTimeString); message.AppendFormat(TEXT("Backup started at %s, completed at %s."), startTimeStringLocal, finishTimeString); OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_NORMAL); message.Empty(); float unitCount = (float)byteCount; LPCTSTR units = TEXT("bytes"); if (unitCount > 1024) { unitCount = unitCount / 1024.0F; units = TEXT("KB"); } if (unitCount > 1024) { unitCount = unitCount / 1024.0F; units = TEXT("MB"); } if (unitCount > 1024) { unitCount = unitCount / 1024.0F; units = TEXT("GB"); } message.AppendFormat(TEXT("%d files (%.2f %s, %d directories) copied, %d files skipped"), fileCount, unitCount, units, directoryCount, skipCount); OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_NORMAL); OutputWriter::SetVerbosityLevel((VERBOSITY_LEVEL)options.get_VerbosityLevel()); //for (int i = 0; i < argc; ++i) //{ // CString message; // message.AppendFormat(TEXT("Argument %d: %s"), i, argv[i]); // OutputWriter::WriteLine(message, VERBOSITY_THRESHOLD_IF_VERBOSE); //} }
void ScreenArcadePatch::PatchMain() { m_State = PATCH_CHECKING; /* NOTE: we used to look for OpenITG prefixed updates also, but the * original ITG binary does not, so if we want people to be able to * upgrade directly from ITG to OITG, we have to continue to use the * "ITG 2 " prefix. Sad times. */ /* set up patterns to match */ CStringArray vsPatterns; vsPatterns.push_back( "ITG 2 *.itg" ); /* check to see if either player has patches */ PlayerNumber pn = PLAYER_INVALID; /* HasPatch() will early abort for us, due to the size() check, * if P1 and P2 both have patches. We just want the first one. */ FOREACH_PlayerNumber( p ) if( this->HasPatch(p, vsPatterns) ) pn = p; /* no matches on either card. */ if( pn == PLAYER_INVALID ) { m_State = PATCH_NONE; return; } /* set the help text to the patch name, blank the patch text */ m_textHelp->SetText( m_vsPatches[0] ); PATCH_TEXT( "" ); /* set up the key paths we want to verify against */ CStringArray vsRSAPaths; vsRSAPaths.push_back( "Data/Patch-OpenITG.rsa" ); vsRSAPaths.push_back( "Data/Patch.rsa" ); /* create the path for the patch file */ CString sPatchFile = m_sProfileDir + m_vsPatches[0]; // copy the patch file into memory // TODO: see if we can FILEMAN->GetFileDriver( "/@mem/" ). m_MemDriver = new RageFileDriverMem; int iError = 0; m_PatchFile = m_MemDriver->Open( ITG_TEMP_FILE, RageFile::WRITE, iError ); if( iError != 0 ) { STATE_TEXT( ssprintf("Failed to open temporary file:\n%s", strerror(iError)) ); m_State = PATCH_ERROR; } /* give up to an hour for the data to copy */ MEMCARDMAN->MountCard( pn, 3600 ); RageFile patch; if( !patch.Open(sPatchFile) ) { STATE_TEXT( ssprintf("Failed to open patch file (%s):\n%s", sPatchFile.c_str(), patch.GetError().c_str()) ); m_State = PATCH_ERROR; } if( m_State == PATCH_ERROR ) { MEMCARDMAN->UnmountCard(pn); return; } CString sError; if( FileCopy( patch, *m_PatchFile, sError, &UpdateProgress) ) { STATE_TEXT( "Patch copied! Checking..." ); PATCH_TEXT( "" ); } else { STATE_TEXT( ssprintf("Patch copying failed:\n" "%s", sError.c_str()) ); m_State = PATCH_ERROR; } MEMCARDMAN->UnmountCard( pn ); if( m_State == PATCH_ERROR ) return; /* re-open the patch file read-open. this should not fail. */ m_PatchFile = m_MemDriver->Open( ITG_TEMP_FILE, RageFile::READ, iError ); if( !this->VerifyPatch(m_PatchFile, vsRSAPaths) ) { PATCH_TEXT( "" ); m_State = PATCH_ERROR; return; } /* reset the error checker */ iError = 0; /* check the XML data */ CString sGame, sSuccessMessage; int iPatchRevision; /* open our new copy and read from it */ RageFileDriverZip *fZip = new RageFileDriverZip( m_PatchFile ); // we'll catch this in a bit, after we've freed our memory if( !this->GetXMLData(fZip, sGame, sSuccessMessage, iPatchRevision) ) m_State = PATCH_ERROR; SAFE_DELETE( fZip ); // if the XML get earlier failed, return now. if( m_State == PATCH_ERROR ) return; // accept patches for oITG or ITG2 if( sGame != "OpenITG" && sGame != "In The Groove 2" ) { sError = ssprintf( "revision is for another game\n" "(\"%s\")", sGame.c_str() ); STATE_TEXT( ssprintf("Cannot proceed: %s", sError.c_str()) ); m_State = PATCH_ERROR; return; } int iCurrentRevision = DiagnosticsUtil::GetRevision(); // HACK: allow any patch at all if it's revision 1. if( iCurrentRevision != 1 && iCurrentRevision == iPatchRevision ) { sError = ssprintf( "patch revision (%d) matches the machine revision.", iPatchRevision ); STATE_TEXT( ssprintf("Cannot proceed: %s", sError.c_str()) ); m_State = PATCH_ERROR; return; } /* wipe any unsucessful or unused patch data */ DeleteRecursive( TEMP_PATCH_DIR ); DeleteRecursive( FINAL_PATCH_DIR ); FILEMAN->CreateDir( TEMP_PATCH_DIR ); /* re-open the ZIP file now */ fZip = new RageFileDriverZip; if( !fZip->Load(m_PatchFile) ) { PATCH_TEXT( "Failed to re-open ZIP file!" ); m_State = PATCH_ERROR; return; } CStringArray vsDirs, vsFiles; vsDirs.push_back( "/" ); /* find all the files we're going to write with a recursive check */ while( vsDirs.size() ) { CString sDir = vsDirs.back(); vsDirs.pop_back(); fZip->GetDirListing( sDir + "/*", vsFiles, false, true ); fZip->GetDirListing( sDir + "/*", vsDirs, true, true ); } PATCH_TEXT( "Extracting files..." ); /* write them now */ for( unsigned i = 0; i < vsFiles.size(); i++ ) { const CString &sPath = vsFiles[i]; CString sCleanPath = sPath; TrimLeft( sCleanPath, "/" ); if( fZip->GetFileType(sPath) != RageFileManager::TYPE_FILE ) continue; LOG->Trace( "ScreenArcadePatch: copying file \"%s\"", sCleanPath.c_str() ); PATCH_TEXT( ssprintf("Extracting files...\n" "%s", sCleanPath.c_str()) ); RageFileBasic *fCopyFrom = fZip->Open( sPath, RageFile::READ, iError ); RageFile fCopyTo; fCopyTo.Open( TEMP_PATCH_DIR + sCleanPath, RageFile::WRITE ); if( !FileCopy(*fCopyFrom, fCopyTo) ) { PATCH_TEXT( ssprintf("Could not copy \"%s\":\n" "%s", sCleanPath.c_str(),sError.c_str()) ); m_State = PATCH_ERROR; SAFE_DELETE( fCopyFrom ); SAFE_DELETE( fZip ); return; } SAFE_DELETE( fCopyFrom ); fCopyTo.Close(); /* set CHMOD info */ #ifdef LINUX /* get the actual path to the files */ CString sRealPath = ResolveTempFilePath( sCleanPath ); const RageFileDriverZip::FileInfo *fi = fZip->GetFileInfo( sPath ); int ret = chmod( sRealPath.c_str(), fi->m_iFilePermissions ); LOG->Trace( "chmod( %s, %#o ) returned %i", sRealPath.c_str(), fi->m_iFilePermissions, ret ); #endif // LINUX } SAFE_DELETE( fZip ); /* clear the previous copying text */ STATE_TEXT( "Finalizing patch data..." ); PATCH_TEXT( "" ); #ifdef LINUX sync(); sleep(5); #endif /* we've successfully copied everything. now, move the directory and we're done. */ if( FILEMAN->Move(TEMP_PATCH_DIR, FINAL_PATCH_DIR) ) { STATE_TEXT( sSuccessMessage ); m_State = PATCH_INSTALLED; } else { STATE_TEXT( "Failed to finalize patch data!\nCheck your system permissions" ); m_State = PATCH_ERROR; } }
static bool CheckPackages( RageFileDriverZip &fileDriver ) { int iErr; RageFileBasic *pFile = fileDriver.Open( "smzip.ctl", RageFile::READ, iErr ); if( pFile == NULL ) return true; IniFile ini; ini.ReadFile( *pFile ); int version = 0; ini.GetValue( "SMZIP", "Version", version ); if( version != 1 ) return true; int cnt = 0; ini.GetValue( "Packages", "NumPackages", cnt ); vector<RString> vsDirectories; for( int i = 0; i < cnt; ++i ) { RString path; if( !ini.GetValue( "Packages", ssprintf("%i", i), path) ) continue; /* Does this directory exist? */ if( !FILEMAN->IsADirectory(path) ) continue; if( !SMPackageUtil::IsValidPackageDirectory(path) ) continue; vsDirectories.push_back(path); } if( vsDirectories.empty() ) return true; { UninstallOld UninstallOldDlg; UninstallOldDlg.m_sPackages = join("\r\n", vsDirectories); int nResponse = UninstallOldDlg.DoModal(); if( nResponse == IDCANCEL ) return false; // cancelled if( nResponse == IDIGNORE ) return true; } char cwd_[MAX_PATH]; _getcwd(cwd_, MAX_PATH); RString cwd(cwd_); if( cwd[cwd.size()-1] != '\\' ) cwd += "\\"; for( int i = 0; i < (int)vsDirectories.size(); ++i ) { RString sDir = vsDirectories[i]; sDir += "/"; if( !DeleteRecursive(sDir) ) // error deleting { return false; } } return true; }