/// <summary> /// Get the binary data representing this instance. /// </summary> /// <returns>The raw binary data representing this instance.</returns> public byte[] GetData() { using (MemoryStream ms = new MemoryStream()) using (BlubbZipHelperStream helperStream = new BlubbZipHelperStream(ms)) { helperStream.IsStreamOwner = false; helperStream.WriteByte((byte)flags_); // Flags if ((flags_ & Flags.ModificationTime) != 0) { TimeSpan span = modificationTime_.ToUniversalTime() - new System.DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime(); int seconds = (int)span.TotalSeconds; helperStream.WriteLEInt(seconds); } if ((flags_ & Flags.AccessTime) != 0) { TimeSpan span = lastAccessTime_.ToUniversalTime() - new System.DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime(); int seconds = (int)span.TotalSeconds; helperStream.WriteLEInt(seconds); } if ((flags_ & Flags.CreateTime) != 0) { TimeSpan span = createTime_.ToUniversalTime() - new System.DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime(); int seconds = (int)span.TotalSeconds; helperStream.WriteLEInt(seconds); } return(ms.ToArray()); } }
/// <summary> /// Set the data from the raw values provided. /// </summary> /// <param name="data">The raw data to extract values from.</param> /// <param name="index">The index to start extracting values from.</param> /// <param name="count">The number of bytes available.</param> public void SetData(byte[] data, int index, int count) { using (MemoryStream ms = new MemoryStream(data, index, count, false)) using (BlubbZipHelperStream helperStream = new BlubbZipHelperStream(ms)) { helperStream.ReadLEInt(); // Reserved while (helperStream.Position < helperStream.Length) { int ntfsTag = helperStream.ReadLEShort(); int ntfsLength = helperStream.ReadLEShort(); if (ntfsTag == 1) { if (ntfsLength >= 24) { long lastModificationTicks = helperStream.ReadLELong(); lastModificationTime_ = DateTime.FromFileTime(lastModificationTicks); long lastAccessTicks = helperStream.ReadLELong(); lastAccessTime_ = DateTime.FromFileTime(lastAccessTicks); long createTimeTicks = helperStream.ReadLELong(); createTime_ = DateTime.FromFileTime(createTimeTicks); } break; } else { // An unknown NTFS tag so simply skip it. helperStream.Seek(ntfsLength, SeekOrigin.Current); } } } }
/// <summary> /// Set the data from the raw values provided. /// </summary> /// <param name="data">The raw data to extract values from.</param> /// <param name="index">The index to start extracting values from.</param> /// <param name="count">The number of bytes available.</param> public void SetData(byte[] data, int index, int count) { using (MemoryStream ms = new MemoryStream(data, index, count, false)) using (BlubbZipHelperStream helperStream = new BlubbZipHelperStream(ms)) { // bit 0 if set, modification time is present // bit 1 if set, access time is present // bit 2 if set, creation time is present flags_ = (Flags)helperStream.ReadByte(); if (((flags_ & Flags.ModificationTime) != 0) && (count >= 5)) { int iTime = helperStream.ReadLEInt(); modificationTime_ = (new System.DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime() + new TimeSpan(0, 0, 0, iTime, 0)).ToLocalTime(); } if ((flags_ & Flags.AccessTime) != 0) { int iTime = helperStream.ReadLEInt(); lastAccessTime_ = (new System.DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime() + new TimeSpan(0, 0, 0, iTime, 0)).ToLocalTime(); } if ((flags_ & Flags.CreateTime) != 0) { int iTime = helperStream.ReadLEInt(); createTime_ = (new System.DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime() + new TimeSpan(0, 0, 0, iTime, 0)).ToLocalTime(); } } }
/// <summary> /// Get the binary data representing this instance. /// </summary> /// <returns>The raw binary data representing this instance.</returns> public byte[] GetData() { using (MemoryStream ms = new MemoryStream()) using (BlubbZipHelperStream helperStream = new BlubbZipHelperStream(ms)) { helperStream.IsStreamOwner = false; helperStream.WriteLEInt(0); // Reserved helperStream.WriteLEShort(1); // Tag helperStream.WriteLEShort(24); // Length = 3 x 8. helperStream.WriteLELong(lastModificationTime_.ToFileTime()); helperStream.WriteLELong(lastAccessTime_.ToFileTime()); helperStream.WriteLELong(createTime_.ToFileTime()); return(ms.ToArray()); } }
/// <summary> /// Test an archive for integrity/validity /// </summary> /// <param name="testData">Perform low level data Crc check</param> /// <param name="strategy">The <see cref="TestStrategy"></see> to apply.</param> /// <param name="resultHandler">The <see cref="BlubbTestResultHandler"></see> handler to call during testing.</param> /// <returns>true if all tests pass, false otherwise</returns> /// <exception cref="ObjectDisposedException">The object has already been closed.</exception> public bool TestArchive( bool testData, TestStrategy strategy, BlubbTestResultHandler resultHandler ) { if( isDisposed_ ) { throw new ObjectDisposedException( "BlubbFile" ); } TestStatus status = new TestStatus( this ); if( resultHandler != null ) { resultHandler( status, null ); } HeaderTest test = testData ? ( HeaderTest.Header | HeaderTest.Extract ) : HeaderTest.Header; bool testing = true; try { int entryIndex = 0; while( testing && ( entryIndex < Count ) ) { if( resultHandler != null ) { status.SetEntry( this[ entryIndex ] ); status.SetOperation( TestOperation.EntryHeader ); resultHandler( status, null ); } try { TestLocalHeader( this[ entryIndex ], test ); } catch( BlubbZipException ex ) { status.AddError(); if( resultHandler != null ) { resultHandler( status, string.Format( "Exception during test - '{0}'", ex.Message ) ); } if( strategy == TestStrategy.FindFirstError ) { testing = false; } } if( testing && testData && this[ entryIndex ].IsFile ) { if( resultHandler != null ) { status.SetOperation( TestOperation.EntryData ); resultHandler( status, null ); } Crc32 crc = new Crc32(); using( Stream entryStream = this.GetInputStream( this[ entryIndex ] ) ) { byte[] buffer = new byte[ 4096 ]; long totalBytes = 0; int bytesRead; while( ( bytesRead = entryStream.Read( buffer, 0, buffer.Length ) ) > 0 ) { crc.Update( buffer, 0, bytesRead ); if( resultHandler != null ) { totalBytes += bytesRead; status.SetBytesTested( totalBytes ); resultHandler( status, null ); } } } if( this[ entryIndex ].Crc != crc.Value ) { status.AddError(); if( resultHandler != null ) { resultHandler( status, "CRC mismatch" ); } if( strategy == TestStrategy.FindFirstError ) { testing = false; } } if( ( this[ entryIndex ].Flags & (int)GeneralBitFlags.Descriptor ) != 0 ) { BlubbZipHelperStream helper = new BlubbZipHelperStream( baseStream_ ); DescriptorData data = new DescriptorData(); helper.ReadDataDescriptor( this[ entryIndex ].LocalHeaderRequiresBlubb64, data ); if( this[ entryIndex ].Crc != data.Crc ) { status.AddError(); } if( this[ entryIndex ].CompressedSize != data.CompressedSize ) { status.AddError(); } if( this[ entryIndex ].Size != data.Size ) { status.AddError(); } } } if( resultHandler != null ) { status.SetOperation( TestOperation.EntryComplete ); resultHandler( status, null ); } entryIndex += 1; } if( resultHandler != null ) { status.SetOperation( TestOperation.MiscellaneousTests ); resultHandler( status, null ); } // TODO: the 'Corrina Johns' test where local headers are missing from // the central directory. They are therefore invisible to many archivers. } catch( Exception ex ) { status.AddError(); if( resultHandler != null ) { resultHandler( status, string.Format( "Exception during test - '{0}'", ex.Message ) ); } } if( resultHandler != null ) { status.SetOperation( TestOperation.Complete ); status.SetEntry( null ); resultHandler( status, null ); } return ( status.ErrorCount == 0 ); }
// NOTE this returns the offset of the first byte after the signature. long LocateBlockWithSignature( int signature, long endLocation, int minimumBlockSize, int maximumVariableData ) { using( BlubbZipHelperStream les = new BlubbZipHelperStream( baseStream_ ) ) { return les.LocateBlockWithSignature( signature, endLocation, minimumBlockSize, maximumVariableData ); } }
void RunUpdates() { long sizeEntries = 0; long endOfStream = 0; bool allOk = true; bool directUpdate = false; long destinationPosition = 0; // NOT SFX friendly BlubbZipFile workFile; if( IsNewArchive ) { workFile = this; workFile.baseStream_.Position = 0; directUpdate = true; } else if( archiveStorage_.UpdateMode == FileUpdateMode.Direct ) { workFile = this; workFile.baseStream_.Position = 0; directUpdate = true; // Sort the updates by offset within copies/modifies, then adds. // This ensures that data required by copies will not be overwritten. updates_.Sort( new UpdateComparer() ); } else { workFile = BlubbZipFile.Create( archiveStorage_.GetTemporaryOutput() ); workFile.UseBlubb64 = UseBlubb64; if( key != null ) { workFile.key = (byte[])key.Clone(); } } try { foreach( BlubbUpdate update in updates_ ) { if( update != null ) { switch( update.Command ) { case UpdateCommand.Copy: if( directUpdate ) { CopyEntryDirect( workFile, update, ref destinationPosition ); } else { CopyEntry( workFile, update ); } break; case UpdateCommand.Modify: // TODO: Direct modifying of an entry will take some legwork. ModifyEntry( workFile, update ); break; case UpdateCommand.Add: if( !IsNewArchive && directUpdate ) { workFile.baseStream_.Position = destinationPosition; } AddEntry( workFile, update ); if( directUpdate ) { destinationPosition = workFile.baseStream_.Position; } break; } } } if( !IsNewArchive && directUpdate ) { workFile.baseStream_.Position = destinationPosition; } long centralDirOffset = workFile.baseStream_.Position; foreach( BlubbUpdate update in updates_ ) { if( update != null ) { sizeEntries += workFile.WriteCentralDirectoryHeader( update.OutEntry ); } } byte[] theComment = ( newComment_ != null ) ? newComment_.RawComment : BlubbZipConstants.ConvertToArray( comment_ ); using( BlubbZipHelperStream zhs = new BlubbZipHelperStream( workFile.baseStream_ ) ) { zhs.WriteEndOfCentralDirectory( updateCount_, sizeEntries, centralDirOffset, theComment ); } endOfStream = workFile.baseStream_.Position; // And now patch entries... foreach( BlubbUpdate update in updates_ ) { if( update != null ) { // If the size of the entry is zero leave the crc as 0 as well. // The calculated crc will be all bits on... if( ( update.CrcPatchOffset > 0 ) && ( update.OutEntry.CompressedSize > 0 ) ) { workFile.baseStream_.Position = update.CrcPatchOffset; workFile.WriteLEInt( (int)update.OutEntry.Crc ); } if( update.SizePatchOffset > 0 ) { workFile.baseStream_.Position = update.SizePatchOffset; if( update.OutEntry.LocalHeaderRequiresBlubb64 ) { workFile.WriteLeLong( update.OutEntry.Size ); workFile.WriteLeLong( update.OutEntry.CompressedSize ); } else { workFile.WriteLEInt( (int)update.OutEntry.CompressedSize ); workFile.WriteLEInt( (int)update.OutEntry.Size ); } } } } } catch( Exception ) { allOk = false; } finally { if( directUpdate ) { if( allOk ) { workFile.baseStream_.Flush(); workFile.baseStream_.SetLength( endOfStream ); } } else { workFile.Close(); } } if( allOk ) { if( directUpdate ) { isNewArchive_ = false; workFile.baseStream_.Flush(); ReadEntries(); } else { baseStream_.Close(); Reopen( archiveStorage_.ConvertTemporaryToFinal() ); } } else { workFile.Close(); if( !directUpdate && ( workFile.Name != null ) ) { File.Delete( workFile.Name ); } } }
void UpdateCommentOnly() { long baseLength = baseStream_.Length; BlubbZipHelperStream updateFile = null; if( archiveStorage_.UpdateMode == FileUpdateMode.Safe ) { Stream copyStream = archiveStorage_.MakeTemporaryCopy( baseStream_ ); updateFile = new BlubbZipHelperStream( copyStream ); updateFile.IsStreamOwner = true; baseStream_.Close(); baseStream_ = null; } else { if( archiveStorage_.UpdateMode == FileUpdateMode.Direct ) { // TODO: archiveStorage wasnt originally intended for this use. // Need to revisit this to tidy up handling as archive storage currently doesnt // handle the original stream well. // The problem is when using an existing blubb archive with an in memory archive storage. // The open stream wont support writing but the memory storage should open the same file not an in memory one. // Need to tidy up the archive storage interface and contract basically. baseStream_ = archiveStorage_.OpenForDirectUpdate( baseStream_ ); updateFile = new BlubbZipHelperStream( baseStream_ ); } else { baseStream_.Close(); baseStream_ = null; updateFile = new BlubbZipHelperStream( Name ); } } using( updateFile ) { long locatedCentralDirOffset = updateFile.LocateBlockWithSignature( BlubbZipConstants.EndOfCentralDirectorySignature, baseLength, BlubbZipConstants.EndOfCentralRecordBaseSize, 0xffff ); if( locatedCentralDirOffset < 0 ) { throw new BlubbZipException( "Cannot find central directory" ); } const int CentralHeaderCommentSizeOffset = 16; updateFile.Position += CentralHeaderCommentSizeOffset; byte[] rawComment = newComment_.RawComment; updateFile.WriteLEShort( rawComment.Length ); updateFile.Write( rawComment, 0, rawComment.Length ); updateFile.SetLength( updateFile.Position ); } if( archiveStorage_.UpdateMode == FileUpdateMode.Safe ) { Reopen( archiveStorage_.ConvertTemporaryToFinal() ); } else { ReadEntries(); } }
void AddEntry( BlubbZipFile workFile, BlubbUpdate update ) { Stream source = null; if( update.Entry.IsFile ) { source = update.GetSource(); if( source == null ) { source = updateDataSource_.GetSource( update.Entry, update.Filename ); } } if( source != null ) { using( source ) { long sourceStreamLength = source.Length; if( update.OutEntry.Size < 0 ) { update.OutEntry.Size = sourceStreamLength; } else { // Check for errant entries. if( update.OutEntry.Size != sourceStreamLength ) { throw new BlubbZipException( "Entry size/stream size mismatch" ); } } workFile.WriteLocalEntryHeader( update ); long dataStart = workFile.baseStream_.Position; using( Stream output = workFile.GetOutputStream( update.OutEntry ) ) { CopyBytes( update, output, source, sourceStreamLength, true ); } long dataEnd = workFile.baseStream_.Position; update.OutEntry.CompressedSize = dataEnd - dataStart; if( ( update.OutEntry.Flags & (int)GeneralBitFlags.Descriptor ) == (int)GeneralBitFlags.Descriptor ) { BlubbZipHelperStream helper = new BlubbZipHelperStream( workFile.baseStream_ ); helper.WriteDataDescriptor( update.OutEntry ); } } } else { workFile.WriteLocalEntryHeader( update ); update.OutEntry.CompressedSize = 0; } }
/// <summary> /// Commit current updates, updating this archive. /// </summary> /// <seealso cref="BeginUpdate()"></seealso> /// <seealso cref="AbortUpdate"></seealso> /// <exception cref="ObjectDisposedException">BlubbFile has been closed.</exception> public void CommitUpdate() { if( isDisposed_ ) { throw new ObjectDisposedException( "BlubbFile" ); } CheckUpdating(); try { updateIndex_.Clear(); updateIndex_ = null; if( contentsEdited_ ) { RunUpdates(); } else if( commentEdited_ ) { UpdateCommentOnly(); } else { // Create an empty archive if none existed originally. if( entries_.Length == 0 ) { byte[] theComment = ( newComment_ != null ) ? newComment_.RawComment : BlubbZipConstants.ConvertToArray( comment_ ); using( BlubbZipHelperStream zhs = new BlubbZipHelperStream( baseStream_ ) ) { zhs.WriteEndOfCentralDirectory( 0, 0, 0, theComment ); } } } } finally { PostUpdateCleanup(); } }
/// <summary> /// Finishes the stream. This will write the central directory at the /// end of the blubb file and flush the stream. /// </summary> /// <remarks> /// This is automatically called when the stream is closed. /// </remarks> /// <exception cref="System.IO.IOException"> /// An I/O error occurs. /// </exception> /// <exception cref="BlubbException"> /// Comment exceeds the maximum length<br/> /// Entry name exceeds the maximum length /// </exception> public override void Finish() { if (entries == null) { return; } if (curEntry != null) { CloseEntry(); } long numEntries = entries.Count; long sizeEntries = 0; foreach (BlubbZipEntry entry in entries) { WriteLeInt(BlubbZipConstants.CentralHeaderSignature); WriteLeShort(BlubbZipConstants.VersionMadeBy); WriteLeShort(entry.Version); WriteLeShort(entry.Flags); WriteLeShort((short)entry.CompressionMethod); WriteLeInt((int)entry.DosTime); WriteLeInt((int)entry.Crc); if (entry.IsBlubb64Forced() || (entry.CompressedSize >= uint.MaxValue)) { WriteLeInt(-1); } else { WriteLeInt((int)entry.CompressedSize); } if (entry.IsBlubb64Forced() || (entry.Size >= uint.MaxValue)) { WriteLeInt(-1); } else { WriteLeInt((int)entry.Size); } byte[] name = BlubbZipConstants.ConvertToArray(entry.Flags, entry.Name); if (name.Length > 0xffff) { throw new BlubbZipException("Name too long."); } BlubbZipExtraData ed = new BlubbZipExtraData(entry.ExtraData); if (entry.CentralHeaderRequiresBlubb64) { ed.StartNewEntry(); if (entry.IsBlubb64Forced() || (entry.Size >= 0xffffffff)) { ed.AddLeLong(entry.Size); } if (entry.IsBlubb64Forced() || (entry.CompressedSize >= 0xffffffff)) { ed.AddLeLong(entry.CompressedSize); } if (entry.Offset >= 0xffffffff) { ed.AddLeLong(entry.Offset); } ed.AddNewEntry(1); } else { ed.Delete(1); } byte[] extra = ed.GetEntryData(); byte[] entryComment = (entry.Comment != null) ? BlubbZipConstants.ConvertToArray(entry.Flags, entry.Comment) : new byte[0]; if (entryComment.Length > 0xffff) { throw new BlubbZipException("Comment too long."); } WriteLeShort(name.Length); WriteLeShort(extra.Length); WriteLeShort(entryComment.Length); WriteLeShort(0); // disk number WriteLeShort(0); // internal file attributes // external file attributes if (entry.ExternalFileAttributes != -1) { WriteLeInt(entry.ExternalFileAttributes); } else { if (entry.IsDirectory) { WriteLeInt(16); } else { WriteLeInt(0); } } if (entry.Offset >= uint.MaxValue) { WriteLeInt(-1); } else { WriteLeInt((int)entry.Offset); } if (name.Length > 0) { baseOutputStream_.Write(name, 0, name.Length); } if (extra.Length > 0) { baseOutputStream_.Write(extra, 0, extra.Length); } if (entryComment.Length > 0) { baseOutputStream_.Write(entryComment, 0, entryComment.Length); } sizeEntries += BlubbZipConstants.CentralHeaderBaseSize + name.Length + extra.Length + entryComment.Length; } using (BlubbZipHelperStream zhs = new BlubbZipHelperStream(baseOutputStream_)) { zhs.WriteEndOfCentralDirectory(numEntries, sizeEntries, offset, blubbComment); } entries = null; }
/// <summary> /// Finishes the stream. This will write the central directory at the /// end of the blubb file and flush the stream. /// </summary> /// <remarks> /// This is automatically called when the stream is closed. /// </remarks> /// <exception cref="System.IO.IOException"> /// An I/O error occurs. /// </exception> /// <exception cref="BlubbException"> /// Comment exceeds the maximum length<br/> /// Entry name exceeds the maximum length /// </exception> public override void Finish() { if( entries == null ) { return; } if( curEntry != null ) { CloseEntry(); } long numEntries = entries.Count; long sizeEntries = 0; foreach( BlubbZipEntry entry in entries ) { WriteLeInt( BlubbZipConstants.CentralHeaderSignature ); WriteLeShort( BlubbZipConstants.VersionMadeBy ); WriteLeShort( entry.Version ); WriteLeShort( entry.Flags ); WriteLeShort( (short)entry.CompressionMethod ); WriteLeInt( (int)entry.DosTime ); WriteLeInt( (int)entry.Crc ); if( entry.IsBlubb64Forced() || ( entry.CompressedSize >= uint.MaxValue ) ) { WriteLeInt( -1 ); } else { WriteLeInt( (int)entry.CompressedSize ); } if( entry.IsBlubb64Forced() || ( entry.Size >= uint.MaxValue ) ) { WriteLeInt( -1 ); } else { WriteLeInt( (int)entry.Size ); } byte[] name = BlubbZipConstants.ConvertToArray( entry.Flags, entry.Name ); if( name.Length > 0xffff ) { throw new BlubbZipException( "Name too long." ); } BlubbZipExtraData ed = new BlubbZipExtraData( entry.ExtraData ); if( entry.CentralHeaderRequiresBlubb64 ) { ed.StartNewEntry(); if( entry.IsBlubb64Forced() || ( entry.Size >= 0xffffffff ) ) { ed.AddLeLong( entry.Size ); } if( entry.IsBlubb64Forced() || ( entry.CompressedSize >= 0xffffffff ) ) { ed.AddLeLong( entry.CompressedSize ); } if( entry.Offset >= 0xffffffff ) { ed.AddLeLong( entry.Offset ); } ed.AddNewEntry( 1 ); } else { ed.Delete( 1 ); } byte[] extra = ed.GetEntryData(); byte[] entryComment = ( entry.Comment != null ) ? BlubbZipConstants.ConvertToArray( entry.Flags, entry.Comment ) : new byte[ 0 ]; if( entryComment.Length > 0xffff ) { throw new BlubbZipException( "Comment too long." ); } WriteLeShort( name.Length ); WriteLeShort( extra.Length ); WriteLeShort( entryComment.Length ); WriteLeShort( 0 ); // disk number WriteLeShort( 0 ); // internal file attributes // external file attributes if( entry.ExternalFileAttributes != -1 ) { WriteLeInt( entry.ExternalFileAttributes ); } else { if( entry.IsDirectory ) { WriteLeInt( 16 ); } else { WriteLeInt( 0 ); } } if( entry.Offset >= uint.MaxValue ) { WriteLeInt( -1 ); } else { WriteLeInt( (int)entry.Offset ); } if( name.Length > 0 ) { baseOutputStream_.Write( name, 0, name.Length ); } if( extra.Length > 0 ) { baseOutputStream_.Write( extra, 0, extra.Length ); } if( entryComment.Length > 0 ) { baseOutputStream_.Write( entryComment, 0, entryComment.Length ); } sizeEntries += BlubbZipConstants.CentralHeaderBaseSize + name.Length + extra.Length + entryComment.Length; } using( BlubbZipHelperStream zhs = new BlubbZipHelperStream( baseOutputStream_ ) ) { zhs.WriteEndOfCentralDirectory( numEntries, sizeEntries, offset, blubbComment ); } entries = null; }
/// <summary> /// Get the binary data representing this instance. /// </summary> /// <returns>The raw binary data representing this instance.</returns> public byte[] GetData() { using( MemoryStream ms = new MemoryStream() ) using( BlubbZipHelperStream helperStream = new BlubbZipHelperStream( ms ) ) { helperStream.IsStreamOwner = false; helperStream.WriteLEInt( 0 ); // Reserved helperStream.WriteLEShort( 1 ); // Tag helperStream.WriteLEShort( 24 ); // Length = 3 x 8. helperStream.WriteLELong( lastModificationTime_.ToFileTime() ); helperStream.WriteLELong( lastAccessTime_.ToFileTime() ); helperStream.WriteLELong( createTime_.ToFileTime() ); return ms.ToArray(); } }
/// <summary> /// Set the data from the raw values provided. /// </summary> /// <param name="data">The raw data to extract values from.</param> /// <param name="index">The index to start extracting values from.</param> /// <param name="count">The number of bytes available.</param> public void SetData( byte[] data, int index, int count ) { using( MemoryStream ms = new MemoryStream( data, index, count, false ) ) using( BlubbZipHelperStream helperStream = new BlubbZipHelperStream( ms ) ) { helperStream.ReadLEInt(); // Reserved while( helperStream.Position < helperStream.Length ) { int ntfsTag = helperStream.ReadLEShort(); int ntfsLength = helperStream.ReadLEShort(); if( ntfsTag == 1 ) { if( ntfsLength >= 24 ) { long lastModificationTicks = helperStream.ReadLELong(); lastModificationTime_ = DateTime.FromFileTime( lastModificationTicks ); long lastAccessTicks = helperStream.ReadLELong(); lastAccessTime_ = DateTime.FromFileTime( lastAccessTicks ); long createTimeTicks = helperStream.ReadLELong(); createTime_ = DateTime.FromFileTime( createTimeTicks ); } break; } else { // An unknown NTFS tag so simply skip it. helperStream.Seek( ntfsLength, SeekOrigin.Current ); } } } }
/// <summary> /// Get the binary data representing this instance. /// </summary> /// <returns>The raw binary data representing this instance.</returns> public byte[] GetData() { using( MemoryStream ms = new MemoryStream() ) using( BlubbZipHelperStream helperStream = new BlubbZipHelperStream( ms ) ) { helperStream.IsStreamOwner = false; helperStream.WriteByte( (byte)flags_ ); // Flags if( ( flags_ & Flags.ModificationTime ) != 0 ) { TimeSpan span = modificationTime_.ToUniversalTime() - new System.DateTime( 1970, 1, 1, 0, 0, 0 ).ToUniversalTime(); int seconds = (int)span.TotalSeconds; helperStream.WriteLEInt( seconds ); } if( ( flags_ & Flags.AccessTime ) != 0 ) { TimeSpan span = lastAccessTime_.ToUniversalTime() - new System.DateTime( 1970, 1, 1, 0, 0, 0 ).ToUniversalTime(); int seconds = (int)span.TotalSeconds; helperStream.WriteLEInt( seconds ); } if( ( flags_ & Flags.CreateTime ) != 0 ) { TimeSpan span = createTime_.ToUniversalTime() - new System.DateTime( 1970, 1, 1, 0, 0, 0 ).ToUniversalTime(); int seconds = (int)span.TotalSeconds; helperStream.WriteLEInt( seconds ); } return ms.ToArray(); } }
/// <summary> /// Set the data from the raw values provided. /// </summary> /// <param name="data">The raw data to extract values from.</param> /// <param name="index">The index to start extracting values from.</param> /// <param name="count">The number of bytes available.</param> public void SetData( byte[] data, int index, int count ) { using( MemoryStream ms = new MemoryStream( data, index, count, false ) ) using( BlubbZipHelperStream helperStream = new BlubbZipHelperStream( ms ) ) { // bit 0 if set, modification time is present // bit 1 if set, access time is present // bit 2 if set, creation time is present flags_ = (Flags)helperStream.ReadByte(); if( ( ( flags_ & Flags.ModificationTime ) != 0 ) && ( count >= 5 ) ) { int iTime = helperStream.ReadLEInt(); modificationTime_ = ( new System.DateTime( 1970, 1, 1, 0, 0, 0 ).ToUniversalTime() + new TimeSpan( 0, 0, 0, iTime, 0 ) ).ToLocalTime(); } if( ( flags_ & Flags.AccessTime ) != 0 ) { int iTime = helperStream.ReadLEInt(); lastAccessTime_ = ( new System.DateTime( 1970, 1, 1, 0, 0, 0 ).ToUniversalTime() + new TimeSpan( 0, 0, 0, iTime, 0 ) ).ToLocalTime(); } if( ( flags_ & Flags.CreateTime ) != 0 ) { int iTime = helperStream.ReadLEInt(); createTime_ = ( new System.DateTime( 1970, 1, 1, 0, 0, 0 ).ToUniversalTime() + new TimeSpan( 0, 0, 0, iTime, 0 ) ).ToLocalTime(); } } }