private void ExtractFileFromStream(
            Stream sourceStream,
            Stream targetStream,
            long fileSize,
            ICryptoTransform decryptor,
            DecompressorCreator createDecompressor,
            Action <double> onProgress,
            CancellationToken cancellationToken)
        {
            using (var cryptoStream = new CryptoStream(sourceStream, decryptor, CryptoStreamMode.Read))
            {
                using (var bufferedCryptoStream = new BufferedStream(new ThreadBufferedStream(cryptoStream, 2 * 1024 * 1024), 2 * 1024 * 1024))
                {
                    //using (var wrapperStream = new GZipReadWrapperStream(bufferedCryptoStream))
                    {
                        using (Stream decompressionStream = createDecompressor(bufferedCryptoStream))
                        {
                            using (var bufferedDecompressionStream = new ThreadBufferedStream(decompressionStream, 4 * 1024 * 1024))
                            {
                                try
                                {
                                    const int bufferSize = 2 * 1024 * 1024;
                                    var       buffer     = new byte[bufferSize];
                                    int       count;

                                    while ((count = bufferedDecompressionStream.Read(buffer, 0, buffer.Length)) > 0)
                                    {
                                        cancellationToken.ThrowIfCancellationRequested();
                                        targetStream.Write(buffer, 0, count);

                                        long bytesProcessed = sourceStream.Position;
                                        onProgress(bytesProcessed / (double)fileSize);
                                    }
                                }
                                catch (OperationCanceledException)
                                {
                                    throw;
                                }
                                catch (Exception e)
                                {
                                    DebugLogger.LogException(e);

                                    PatcherLogManager        logManager     = PatcherLogManager.Instance;
                                    PatcherLogSentryRegistry sentryRegistry = logManager.SentryRegistry;
                                    RavenClient ravenClient = sentryRegistry.RavenClient;

                                    var sentryEvent = new SentryEvent(e);
                                    PatcherLogSentryRegistry.AddDataToSentryEvent(sentryEvent,
                                                                                  logManager.Storage.Guid.ToString());
                                    ravenClient.Capture(sentryEvent);

                                    throw;
                                }
                            }
                        }
                    }
                }
            }
        }
        private void UnpackRegularFile(Pack1Meta.FileEntry file, Action <double> onProgress)
        {
            string destPath = Path.Combine(_destinationDirPath, file.Name + _suffix);

            DebugLogger.LogFormat("Unpacking regular file {0} to {1}", file, destPath);

            Files.CreateParents(destPath);

            RijndaelManaged rijn = new RijndaelManaged
            {
                Mode    = CipherMode.CBC,
                Padding = PaddingMode.None,
                KeySize = 256
            };

            using (var fs = new FileStream(_packagePath, FileMode.Open))
            {
                fs.Seek(file.Offset.Value, SeekOrigin.Begin);

                using (var limitedStream = new LimitedStream(fs, file.Size.Value))
                {
                    ICryptoTransform decryptor = rijn.CreateDecryptor(_key, _iv);
                    using (var cryptoStream = new CryptoStream(limitedStream, decryptor, CryptoStreamMode.Read))
                    {
                        using (var gzipStream = new GZipStream(cryptoStream, Ionic.Zlib.CompressionMode.Decompress))
                        {
                            try
                            {
                                using (var fileWritter = new FileStream(destPath, FileMode.Create))
                                {
                                    long      bytesProcessed = 0;
                                    const int bufferSize     = 131072;
                                    var       buffer         = new byte[bufferSize];
                                    int       count;
                                    while ((count = gzipStream.Read(buffer, 0, bufferSize)) != 0)
                                    {
                                        fileWritter.Write(buffer, 0, count);
                                        bytesProcessed += count;
                                        onProgress(bytesProcessed / (double)file.Size.Value);
                                    }
                                    if (Platform.IsPosix())
                                    {
                                        Chmod.SetMode(file.Mode.Substring(3), destPath);
                                    }
                                }
                            }
                            catch (Exception e)
                            {
                                DebugLogger.LogException(e);

                                var ravenClient
                                    = new RavenClient("https://*****:*****@sentry.io/175617");

                                var sentryEvent = new SentryEvent(e);
                                var logManager  = PatcherLogManager.Instance;
                                PatcherLogSentryRegistry.AddDataToSentryEvent(sentryEvent, logManager.Storage.Guid.ToString());

                                ravenClient.Capture(sentryEvent);

                                throw;
                            }
                        }
                    }
                }
            }

            DebugLogger.Log("File " + file.Name + " unpacked successfully!");
        }