/// <summary> /// Moves to the next archive in the sequence if necessary. /// </summary> private void CheckArchiveWriteStream( IPackStreamContext streamContext, long maxArchiveSize, long requiredSize, ref Stream archiveStream) { if (archiveStream != null && archiveStream.Length > 0 && maxArchiveSize > 0) { long sizeRemaining = maxArchiveSize - archiveStream.Length; if (sizeRemaining < requiredSize) { string nextArchiveName = streamContext.GetArchiveName( this.currentArchiveNumber + 1); if (string.IsNullOrWhiteSpace(nextArchiveName)) { throw new FileNotFoundException("No name provided for archive #" + this.currentArchiveNumber + 1); } this.currentArchiveTotalBytes = archiveStream.Position; this.currentArchiveBytesProcessed = this.currentArchiveTotalBytes; streamContext.CloseArchiveWriteStream( this.currentArchiveNumber, nextArchiveName, archiveStream); archiveStream = null; this.OnProgress(ArchiveProgressType.FinishArchive); this.currentArchiveNumber++; this.totalArchives++; this.currentArchiveBytesProcessed = 0; this.currentArchiveTotalBytes = 0; } } if (archiveStream == null) { if (this.currentArchiveNumber > 0) { this.OnProgress(ArchiveProgressType.StartArchive); } archiveStream = streamContext.OpenArchiveWriteStream( this.currentArchiveNumber, this.mainArchiveName, true, this); if (archiveStream == null) { throw new FileNotFoundException("Stream not provided for archive #" + this.currentArchiveNumber); } } }
internal override int CabOpenStreamEx(string path, int openFlags, int shareMode, out int err, IntPtr pv) { if (CabNumbers.ContainsKey(path)) { Stream stream = CabStream; if (stream == null) { short cabNumber = CabNumbers[path]; currentFolderTotalBytes = 0; stream = context.OpenArchiveWriteStream(cabNumber, path, true, CabEngine); if (stream == null) { throw new FileNotFoundException( String.Format(CultureInfo.InvariantCulture, "Cabinet {0} not provided.", cabNumber)); } currentArchiveName = path; currentArchiveTotalBytes = Math.Min( totalFolderBytesProcessedInCurrentCab, maxCabBytes); currentArchiveBytesProcessed = 0; OnProgress(ArchiveProgressType.StartArchive); CabStream = stream; } path = CabStreamName; } else if (path == TempStreamName) { // Opening memory stream for a temp file. Stream stream = new MemoryStream(); tempStreams.Add(stream); int streamHandle = StreamHandles.AllocHandle(stream); err = 0; return(streamHandle); } else if (path != CabStreamName) { // Opening a file on disk for a temp file. path = Path.Combine(Path.GetTempPath(), path); Stream stream = new FileStream(path, FileMode.Open, FileAccess.ReadWrite); tempStreams.Add(stream); stream = new DuplicateStream(stream); int streamHandle = StreamHandles.AllocHandle(stream); err = 0; return(streamHandle); } return(base.CabOpenStreamEx(path, openFlags, shareMode, out err, pv)); }
internal override int CabOpenStreamEx(string path, int openFlags, int shareMode, out int err, IntPtr pv) { if (base.CabNumbers.ContainsKey(path)) { Stream cabStream = base.CabStream; if (cabStream == null) { short num = base.CabNumbers[path]; currentFolderTotalBytes = 0L; cabStream = context.OpenArchiveWriteStream(num, path, truncate: true, base.CabEngine); if (cabStream == null) { throw new FileNotFoundException(string.Format(CultureInfo.InvariantCulture, "Cabinet {0} not provided.", num)); } currentArchiveName = path; currentArchiveTotalBytes = Math.Min(totalFolderBytesProcessedInCurrentCab, maxCabBytes); currentArchiveBytesProcessed = 0L; OnProgress(ArchiveProgressType.StartArchive); base.CabStream = cabStream; } path = "%%CAB%%"; } else { if (path == "%%TEMP%%") { Stream stream = new MemoryStream(); tempStreams.Add(stream); int result = base.StreamHandles.AllocHandle(stream); err = 0; return(result); } if (path != "%%CAB%%") { path = Path.Combine(Path.GetTempPath(), path); Stream stream2 = new FileStream(path, FileMode.Open, FileAccess.ReadWrite); tempStreams.Add(stream2); stream2 = new DuplicateStream(stream2); int result2 = base.StreamHandles.AllocHandle(stream2); err = 0; return(result2); } } return(base.CabOpenStreamEx(path, openFlags, shareMode, out err, pv)); }
/// <summary> /// Adds one file to a zip archive in the process of being created. /// </summary> private ZipFileHeader PackOneFile( IPackStreamContext streamContext, string file, long maxArchiveSize, bool forceZip64, ref Stream archiveStream) { Stream fileStream = null; int headerArchiveNumber = 0; try { // TODO: call GetOption to get compression method for the specific file ZipCompressionMethod compressionMethod = ZipCompressionMethod.Deflate; if (this.CompressionLevel == CompressionLevel.None) { compressionMethod = ZipCompressionMethod.Store; } Converter<Stream, Stream> compressionStreamCreator; if (!ZipEngine.compressionStreamCreators.TryGetValue( compressionMethod, out compressionStreamCreator)) { return null; } FileAttributes attributes; DateTime lastWriteTime; fileStream = streamContext.OpenFileReadStream( file, out attributes, out lastWriteTime); if (fileStream == null) { return null; } this.currentFileName = file; this.currentFileNumber++; this.currentFileTotalBytes = fileStream.Length; this.currentFileBytesProcessed = 0; this.OnProgress(ArchiveProgressType.StartFile); ZipFileInfo fileInfo = new ZipFileInfo( file, this.currentArchiveNumber, attributes, lastWriteTime, fileStream.Length, 0, compressionMethod); bool zip64 = forceZip64 || fileStream.Length >= (long) UInt32.MaxValue; ZipFileHeader fileHeader = new ZipFileHeader(fileInfo, zip64); this.CheckArchiveWriteStream( streamContext, maxArchiveSize, fileHeader.GetSize(false), ref archiveStream); long headerPosition = archiveStream.Position; fileHeader.Write(archiveStream, false); headerArchiveNumber = this.currentArchiveNumber; uint crc; long bytesWritten = this.PackFileBytes( streamContext, fileStream, maxArchiveSize, compressionStreamCreator, ref archiveStream, out crc); fileHeader.Update( bytesWritten, fileStream.Length, crc, headerPosition, headerArchiveNumber); streamContext.CloseFileReadStream(file, fileStream); fileStream = null; // Go back and rewrite the updated file header. if (this.currentArchiveNumber == headerArchiveNumber) { long fileEndPosition = archiveStream.Position; archiveStream.Seek(headerPosition, SeekOrigin.Begin); fileHeader.Write(archiveStream, false); archiveStream.Seek(fileEndPosition, SeekOrigin.Begin); } else { // The file spanned archives, so temporarily reopen // the archive where it started. string headerArchiveName = streamContext.GetArchiveName( headerArchiveNumber + 1); Stream headerStream = null; try { headerStream = streamContext.OpenArchiveWriteStream( headerArchiveNumber, headerArchiveName, false, this); headerStream.Seek(headerPosition, SeekOrigin.Begin); fileHeader.Write(headerStream, false); } finally { if (headerStream != null) { streamContext.CloseArchiveWriteStream( headerArchiveNumber, headerArchiveName, headerStream); } } } this.OnProgress(ArchiveProgressType.FinishFile); return fileHeader; } finally { if (fileStream != null) { streamContext.CloseFileReadStream( this.currentFileName, fileStream); } } }
/// <summary> /// Adds one file to a zip archive in the process of being created. /// </summary> private ZipFileHeader PackOneFile( IPackStreamContext streamContext, string file, long maxArchiveSize, bool forceZip64, ref Stream archiveStream) { Stream fileStream = null; int headerArchiveNumber = 0; try { // TODO: call GetOption to get compression method for the specific file ZipCompressionMethod compressionMethod = ZipCompressionMethod.Deflate; if (this.CompressionLevel == CompressionLevel.None) { compressionMethod = ZipCompressionMethod.Store; } Func <Stream, Stream> compressionStreamCreator; if (!ZipEngine.compressionStreamCreators.TryGetValue( compressionMethod, out compressionStreamCreator)) { return(null); } FileAttributes attributes; DateTime lastWriteTime; fileStream = streamContext.OpenFileReadStream( file, out attributes, out lastWriteTime); if (fileStream == null) { return(null); } this.currentFileName = file; this.currentFileNumber++; this.currentFileTotalBytes = fileStream.Length; this.currentFileBytesProcessed = 0; this.OnProgress(ArchiveProgressType.StartFile); ZipFileInfo fileInfo = new ZipFileInfo( file, this.currentArchiveNumber, attributes, lastWriteTime, fileStream.Length, 0, compressionMethod); bool zip64 = forceZip64 || fileStream.Length >= (long)UInt32.MaxValue; ZipFileHeader fileHeader = new ZipFileHeader(fileInfo, zip64); this.CheckArchiveWriteStream( streamContext, maxArchiveSize, fileHeader.GetSize(false), ref archiveStream); long headerPosition = archiveStream.Position; fileHeader.Write(archiveStream, false); headerArchiveNumber = this.currentArchiveNumber; uint crc; long bytesWritten = this.PackFileBytes( streamContext, fileStream, maxArchiveSize, compressionStreamCreator, ref archiveStream, out crc); fileHeader.Update( bytesWritten, fileStream.Length, crc, headerPosition, headerArchiveNumber); streamContext.CloseFileReadStream(file, fileStream); fileStream = null; // Go back and rewrite the updated file header. if (this.currentArchiveNumber == headerArchiveNumber) { long fileEndPosition = archiveStream.Position; archiveStream.Seek(headerPosition, SeekOrigin.Begin); fileHeader.Write(archiveStream, false); archiveStream.Seek(fileEndPosition, SeekOrigin.Begin); } else { // The file spanned archives, so temporarily reopen // the archive where it started. string headerArchiveName = streamContext.GetArchiveName( headerArchiveNumber + 1); Stream headerStream = null; try { headerStream = streamContext.OpenArchiveWriteStream( headerArchiveNumber, headerArchiveName, false, this); headerStream.Seek(headerPosition, SeekOrigin.Begin); fileHeader.Write(headerStream, false); } finally { if (headerStream != null) { streamContext.CloseArchiveWriteStream( headerArchiveNumber, headerArchiveName, headerStream); } } } this.OnProgress(ArchiveProgressType.FinishFile); return(fileHeader); } finally { if (fileStream != null) { streamContext.CloseFileReadStream( this.currentFileName, fileStream); } } }