/// <summary> /// Starts a read-only transaction. /// </summary> /// <remarks> /// This puts the archive into read-only mode. /// </remarks> /// <param name="p_futFileUtil">An instance of a <see cref="FileUtil"/> class.</param> /// <exception cref="ArgumentNullException">Thrown if <paramref name="p_futFileUtil"/> is <c>null</c>.</exception> public void BeginReadOnlyTransaction(FileUtil p_futFileUtil) { if (m_szeReadOnlyExtractor == null) { if (p_futFileUtil == null) { throw new ArgumentNullException("p_futFileUtil"); } m_szeReadOnlyExtractor = GetThreadSafeExtractor(m_strPath); if (m_szeReadOnlyExtractor.IsSolid) { m_szeReadOnlyExtractor.Dispose(); m_szeReadOnlyExtractor = null; m_strReadOnlyTempDirectory = p_futFileUtil.CreateTempDirectory(); using (SevenZipExtractor szeExtractor = Archive.GetExtractor(m_strPath)) { szeExtractor.FileExtractionFinished += new EventHandler <FileInfoEventArgs>(FileExtractionFinished); szeExtractor.ExtractArchive(m_strReadOnlyTempDirectory); } } } }
/// <summary> /// Starts a read-only transaction. /// </summary> /// <remarks> /// This puts the OMod into read-only mode. /// /// Read-only mode can greatly increase the speed at which multiple file are extracted. /// </remarks> public void BeginReadOnlyTransaction(FileUtil p_futFileUtil) { if (!IsPacked) { m_arcFile.ReadOnlyInitProgressUpdated += new CancelProgressEventHandler(ArchiveFile_ReadOnlyInitProgressUpdated); m_arcFile.BeginReadOnlyTransaction(p_futFileUtil); return; } m_strReadOnlyTempDirectory = p_futFileUtil.CreateTempDirectory(); string[] strFileStreamNames = { "plugins", "data" }; List<FileInfo> lstFiles = null; byte[] bteUncompressedFileData = null; m_intReadOnlyInitFileBlockExtractionCurrentStage = 0; m_fltReadOnlyInitCurrentBaseProgress = 0; foreach (string strFileStreamName in strFileStreamNames) { //extract the compressed file block... using (Stream stmCompressedFiles = new MemoryStream()) { using (SevenZipExtractor szeOmod = new SevenZipExtractor(m_strFilePath)) { if (!szeOmod.ArchiveFileNames.Contains(strFileStreamName)) continue; m_intReadOnlyInitFileBlockExtractionCurrentStage++; szeOmod.ExtractFile(strFileStreamName, stmCompressedFiles); switch (strFileStreamName) { case "plugins": lstFiles = PluginList; break; case "data": lstFiles = DataFileList; break; default: throw new Exception("Unexpected value for file stream name: " + strFileStreamName); } } stmCompressedFiles.Position = 0; Int64 intTotalLength = lstFiles.Sum(x => x.Length); bteUncompressedFileData = new byte[intTotalLength]; switch (CompressionType) { case InArchiveFormat.SevenZip: byte[] bteProperties = new byte[5]; stmCompressedFiles.Read(bteProperties, 0, 5); Decoder dcrDecoder = new Decoder(); dcrDecoder.SetDecoderProperties(bteProperties); DecoderProgressWatcher dpwWatcher = new DecoderProgressWatcher(stmCompressedFiles.Length); dpwWatcher.ProgressUpdated += new EventHandler<EventArgs<int>>(dpwWatcher_ProgressUpdated); using (Stream stmUncompressedFiles = new MemoryStream(bteUncompressedFileData)) dcrDecoder.Code(stmCompressedFiles, stmUncompressedFiles, stmCompressedFiles.Length - stmCompressedFiles.Position, intTotalLength, dpwWatcher); break; case InArchiveFormat.Zip: using (SevenZipExtractor szeZip = new SevenZipExtractor(stmCompressedFiles)) { szeZip.Extracting += new EventHandler<ProgressEventArgs>(szeZip_Extracting); using (Stream stmFile = new MemoryStream(bteUncompressedFileData)) { szeZip.ExtractFile(0, stmFile); } } break; default: throw new Exception("Cannot get files: unsupported compression type: " + CompressionType.ToString()); } } float fltFileStreamPercentBlockSize = FILE_BLOCK_EXTRACTION_PROGRESS_BLOCK_SIZE / m_intReadOnlyInitFileBlockExtractionStages; float fltFileWritingPercentBlockSize = FILE_WRITE_PROGRESS_BLOCK_SIZE / m_intReadOnlyInitFileBlockExtractionStages; m_fltReadOnlyInitCurrentBaseProgress += fltFileStreamPercentBlockSize; //...then write each file to the temporary location Int64 intFileStart = 0; byte[] bteFile = null; Crc32 crcChecksum = new Crc32(); for (Int32 i = 0; i < lstFiles.Count; i++) { FileInfo ofiFile = lstFiles[i]; bteFile = new byte[ofiFile.Length]; Array.Copy(bteUncompressedFileData, intFileStart, bteFile, 0, ofiFile.Length); intFileStart += ofiFile.Length; FileUtil.WriteAllBytes(Path.Combine(m_strReadOnlyTempDirectory, ofiFile.Name), bteFile); crcChecksum.Initialize(); crcChecksum.ComputeHash(bteFile); if (crcChecksum.CrcValue != ofiFile.CRC) throw new Exception(String.Format("Unable to extract {0}: checksums did not match. OMod is corrupt.", ofiFile.Name)); UpdateReadOnlyInitProgress(m_fltReadOnlyInitCurrentBaseProgress, fltFileWritingPercentBlockSize, i / lstFiles.Count); } m_fltReadOnlyInitCurrentBaseProgress += fltFileWritingPercentBlockSize; } m_fltReadOnlyInitCurrentBaseProgress = FILE_BLOCK_EXTRACTION_PROGRESS_BLOCK_SIZE + FILE_WRITE_PROGRESS_BLOCK_SIZE; Int32 intRemainingSteps = (m_booHasInstallScript ? 1 : 0) + (m_booHasReadme ? 1 : 0) + (m_booHasScreenshot ? 1 : 0); Int32 intStepCounter = 1; if (m_booHasScreenshot) { File.WriteAllBytes(Path.Combine(m_strReadOnlyTempDirectory, ScreenshotPath), GetSpecialFile(ScreenshotPath)); UpdateReadOnlyInitProgress(m_fltReadOnlyInitCurrentBaseProgress, 1f - m_fltReadOnlyInitCurrentBaseProgress, 1f / intRemainingSteps * intStepCounter++); } if (m_booHasInstallScript) { File.WriteAllBytes(Path.Combine(m_strReadOnlyTempDirectory, "script"), GetSpecialFile("script")); UpdateReadOnlyInitProgress(m_fltReadOnlyInitCurrentBaseProgress, 1f - m_fltReadOnlyInitCurrentBaseProgress, 1f / intRemainingSteps * intStepCounter++); } if (m_booHasReadme) { File.WriteAllBytes(Path.Combine(m_strReadOnlyTempDirectory, "readme"), GetSpecialFile("readme")); UpdateReadOnlyInitProgress(m_fltReadOnlyInitCurrentBaseProgress, 1f - m_fltReadOnlyInitCurrentBaseProgress, 1f / intRemainingSteps * intStepCounter); } }
/// <summary> /// Starts a read-only transaction. /// </summary> /// <remarks> /// This puts the archive into read-only mode. /// </remarks> /// <param name="p_futFileUtil">An instance of a <see cref="FileUtil"/> class.</param> /// <exception cref="ArgumentNullException">Thrown if <paramref name="p_futFileUtil"/> is <c>null</c>.</exception> public void BeginReadOnlyTransaction(FileUtil p_futFileUtil) { if (m_szeReadOnlyExtractor == null) { if (p_futFileUtil == null) throw new ArgumentNullException("p_futFileUtil"); m_szeReadOnlyExtractor = GetThreadSafeExtractor(m_strPath); if (m_szeReadOnlyExtractor.IsSolid) { m_szeReadOnlyExtractor.Dispose(); m_szeReadOnlyExtractor = null; m_strReadOnlyTempDirectory = p_futFileUtil.CreateTempDirectory(); using (SevenZipExtractor szeExtractor = Archive.GetExtractor(m_strPath)) { szeExtractor.FileExtractionFinished += new EventHandler<FileInfoEventArgs>(FileExtractionFinished); szeExtractor.ExtractArchive(m_strReadOnlyTempDirectory); } } } }