This class encapsulates the Tar Entry Header used in Tar Archives. The class also holds a number of tar constants, used mostly in headers.
Наследование: ICloneable
Пример #1
1
		private void WriteObjectToTar (TarOutputStream  tar_out,
					       FileSystemObject fso,
					       EventTracker     tracker)
		{
			MemoryStream memory = null;

			TarHeader header;
			header = new TarHeader ();

			StringBuilder name_builder;
			name_builder = new StringBuilder (fso.FullName);
			name_builder.Remove (0, this.FullName.Length+1);
			header.Name = name_builder.ToString ();

			header.ModTime = fso.Timestamp;
			if (fso is DirectoryObject) {
				header.Mode = 511; // 0777
				header.TypeFlag = TarHeader.LF_DIR;
				header.Size = 0;
			} else {
				header.Mode = 438; // 0666
				header.TypeFlag = TarHeader.LF_NORMAL;
				memory = new MemoryStream ();
				((FileObject) fso).AddToStream (memory, tracker);
				header.Size = memory.Length;
			}

			TarEntry entry;
			entry = new TarEntry (header);

			tar_out.PutNextEntry (entry);
			if (memory != null) {
				tar_out.Write (memory.ToArray (), 0, (int) memory.Length);
				memory.Close ();
			}
			tar_out.CloseEntry ();

			// If this is a directory, write out the children
			if (fso is DirectoryObject)
				foreach (FileSystemObject child in fso.Children)
					WriteObjectToTar (tar_out, child, tracker);
		}
Пример #2
0
        /// <summary>
        /// Construct a TarEntry using the <paramref name="header">header</paramref> provided
        /// </summary>
        /// <param name="header">Header details for entry</param>
        public TarEntry(TarHeader header)
        {
            if (header == null) {
                throw new ArgumentNullException("TarHeader");
            }

            this.header = (TarHeader)header.Clone();
        }
Пример #3
0
		/// <summary>
		/// Clone a TAR header.
		/// </summary>
		public object Clone()
		{
			TarHeader hdr = new TarHeader();
			
			hdr.Name      = Name;
			hdr.Mode      = this.Mode;
			hdr.UserId    = this.UserId;
			hdr.GroupId   = this.GroupId;
			hdr.Size      = this.Size;
			hdr.ModTime   = this.ModTime;
			hdr.TypeFlag  = this.TypeFlag;
			hdr.LinkName  = this.LinkName;
			hdr.Magic     = this.Magic;
			hdr.Version   = this.Version;
			hdr.UserName  = this.UserName;
			hdr.GroupName = this.GroupName;
			hdr.DevMajor  = this.DevMajor;
			hdr.DevMinor  = this.DevMinor;
			
			return hdr;
		}
Пример #4
0
        public TarEntry GetNextEntry()
        {
            if (this.hasHitEOF) {
                return null;
            }

            if (this.currentEntry != null) {
                SkipToNextEntry();
            }

            byte[] headerBuf = this.buffer.ReadBlock();

            if (headerBuf == null) {
                this.hasHitEOF = true;
            } else if (TarBuffer.IsEndOfArchiveBlock(headerBuf)) {
                this.hasHitEOF = true;
            }

            if (this.hasHitEOF) {
                this.currentEntry = null;
            } else {
                try {
                    TarHeader header = new TarHeader();
                    header.ParseBuffer(headerBuf);
                    if ( !header.IsChecksumValid )
                    {
                        throw new TarException("Header checksum is invalid");
                    }
                    this.entryOffset = 0;
                    this.entrySize = header.Size;

                    StringBuilder longName = null;

                    if (header.TypeFlag == TarHeader.LF_GNU_LONGNAME) {

                        byte[] nameBuffer = new byte[TarBuffer.BlockSize];
                        long numToRead = this.entrySize;

                        longName = new StringBuilder();

                        while (numToRead > 0) {
                            int numRead = this.Read(nameBuffer, 0, (numToRead > nameBuffer.Length ? nameBuffer.Length : (int)numToRead));

                            if (numRead == -1) {
                                throw new InvalidHeaderException("Failed to read long name entry");
                            }

                            longName.Append(TarHeader.ParseName(nameBuffer, 0, numRead).ToString());
                            numToRead -= numRead;
                        }

                        SkipToNextEntry();
                        headerBuf = this.buffer.ReadBlock();
                    } else if (header.TypeFlag == TarHeader.LF_GHDR) {

                        SkipToNextEntry();
                        headerBuf = this.buffer.ReadBlock();
                    } else if (header.TypeFlag == TarHeader.LF_XHDR) {

                        SkipToNextEntry();
                        headerBuf = this.buffer.ReadBlock();
                    } else if (header.TypeFlag == TarHeader.LF_GNU_VOLHDR) {

                        SkipToNextEntry();
                        headerBuf = this.buffer.ReadBlock();
                    } else if (header.TypeFlag != TarHeader.LF_NORMAL &&
                               header.TypeFlag != TarHeader.LF_OLDNORM &&
                               header.TypeFlag != TarHeader.LF_DIR) {

                        SkipToNextEntry();
                        headerBuf = this.buffer.ReadBlock();
                    }

                    if (this.entryFactory == null) {
                        this.currentEntry = new TarEntry(headerBuf);
                        if (longName != null) {
                            currentEntry.Name = longName.ToString();
                        }
                    } else {
                        this.currentEntry = this.entryFactory.CreateEntry(headerBuf);
                    }

                    this.entryOffset = 0;

                    this.entrySize = this.currentEntry.Size;
                } catch (InvalidHeaderException ex) {
                    this.entrySize = 0;
                    this.entryOffset = 0;
                    this.currentEntry = null;
                    string errorText = string.Format("Bad header in record {0} block {1} {2}",
                        buffer.CurrentRecord, buffer.CurrentBlock, ex.Message);
                    throw new InvalidHeaderException(errorText);
                }
            }
            return this.currentEntry;
        }
Пример #5
0
 /// <summary>
 /// Add the checksum integer to header buffer.
 /// </summary>
 /// <param name = "value"></param>
 /// <param name = "buffer">The header buffer to set the checksum for</param>
 /// <param name = "offset">The offset into the buffer for the checksum</param>
 /// <param name = "length">The number of header bytes to update.
 /// It's formatted differently from the other fields: it has 6 digits, a
 /// null, then a space -- rather than digits, a space, then a null.
 /// The final space is already there, from checksumming
 /// </param>
 /// <returns>The modified buffer offset</returns>
 static int GetCheckSumOctalBytes(long value, byte[] buffer, int offset, int length)
 {
     TarHeader.GetOctalBytes(value, buffer, offset, length - 1);
     return(offset + length);
 }
Пример #6
0
 public TarEntry GetNextEntry()
 {
     if (hasHitEOF)
     {
         return(null);
     }
     if (currentEntry != null)
     {
         SkipToNextEntry();
     }
     byte[] array = tarBuffer.ReadBlock();
     if (array == null)
     {
         hasHitEOF = true;
     }
     else if (TarBuffer.IsEndOfArchiveBlock(array))
     {
         hasHitEOF = true;
     }
     if (hasHitEOF)
     {
         currentEntry = null;
     }
     else
     {
         try
         {
             TarHeader tarHeader = new TarHeader();
             tarHeader.ParseBuffer(array);
             if (!tarHeader.IsChecksumValid)
             {
                 throw new TarException("Header checksum is invalid");
             }
             entryOffset = 0L;
             entrySize   = tarHeader.Size;
             StringBuilder stringBuilder = null;
             if (tarHeader.TypeFlag == 76)
             {
                 byte[] array2 = new byte[512];
                 long   num    = entrySize;
                 stringBuilder = new StringBuilder();
                 while (num > 0)
                 {
                     int num2 = Read(array2, 0, (int)((num > array2.Length) ? array2.Length : num));
                     if (num2 == -1)
                     {
                         throw new InvalidHeaderException("Failed to read long name entry");
                     }
                     stringBuilder.Append(TarHeader.ParseName(array2, 0, num2).ToString());
                     num -= num2;
                 }
                 SkipToNextEntry();
                 array = tarBuffer.ReadBlock();
             }
             else if (tarHeader.TypeFlag == 103)
             {
                 SkipToNextEntry();
                 array = tarBuffer.ReadBlock();
             }
             else if (tarHeader.TypeFlag == 120)
             {
                 SkipToNextEntry();
                 array = tarBuffer.ReadBlock();
             }
             else if (tarHeader.TypeFlag == 86)
             {
                 SkipToNextEntry();
                 array = tarBuffer.ReadBlock();
             }
             else if (tarHeader.TypeFlag != 48 && tarHeader.TypeFlag != 0 && tarHeader.TypeFlag != 53)
             {
                 SkipToNextEntry();
                 array = tarBuffer.ReadBlock();
             }
             if (entryFactory == null)
             {
                 currentEntry = new TarEntry(array);
                 if (stringBuilder != null)
                 {
                     currentEntry.Name = stringBuilder.ToString();
                 }
             }
             else
             {
                 currentEntry = entryFactory.CreateEntry(array);
             }
             entryOffset = 0L;
             entrySize   = currentEntry.Size;
         }
         catch (InvalidHeaderException ex)
         {
             entrySize    = 0L;
             entryOffset  = 0L;
             currentEntry = null;
             string message = $"Bad header in record {tarBuffer.CurrentRecord} block {tarBuffer.CurrentBlock} {ex.Message}";
             throw new InvalidHeaderException(message);
         }
     }
     return(currentEntry);
 }
Пример #7
0
		/// <summary>
		/// TarHeaders can be cloned.
		/// </summary>
		public object Clone()
		{
			TarHeader hdr = new TarHeader();
			
			hdr.name      = (this.name == null) ? null : new StringBuilder(this.name.ToString());
			hdr.mode      = this.mode;
			hdr.userId    = this.userId;
			hdr.groupId   = this.groupId;
			hdr.size      = this.size;
			hdr.modTime   = this.modTime;
			hdr.checkSum  = this.checkSum;
			hdr.typeFlag  = this.typeFlag;
			hdr.linkName  = (this.linkName == null)  ? null : new StringBuilder(this.linkName.ToString());
			hdr.magic     = (this.magic == null)     ? null : new StringBuilder(this.magic.ToString());
         hdr.version   = (this.version == null)   ? null : new StringBuilder(this.version.ToString());
			hdr.userName  = (this.userName == null)  ? null : new StringBuilder(this.userName.ToString());
			hdr.groupName = (this.groupName == null) ? null : new StringBuilder(this.groupName.ToString());
			hdr.devMajor  = this.devMajor;
			hdr.devMinor  = this.devMinor;
			
			return hdr;
		}
Пример #8
0
		/// <summary>
		/// Fill in a TarHeader given only the entry's name.
		/// </summary>
		/// <param name="hdr">
		/// The TarHeader to fill in.
		/// </param>
		/// <param name="name">
		/// The tar entry name.
		/// </param>
		public void NameTarHeader(TarHeader hdr, string name)
		{
			bool isDir = name.EndsWith("/");   // -jr- this is true for BSD tar but not all others I think?
			
			hdr.checkSum = 0;
			
			hdr.name = new StringBuilder(name);
//			hdr.mode = isDir ? 040755 : 0100644; // TODO : I think I've seen these magics before ...
         hdr.mode = isDir ? 1003 : 33216;
         hdr.userId   = 0;
			hdr.groupId  = 0;
			hdr.size     = 0;
			hdr.checkSum = 0;
			
         hdr.modTime  = DateTime.UtcNow;        // -jr- 24-Jan-2004 Unix times are in utc!
//			hdr.modTime  = DateTime.Now;   // (new java.util.Date()).getTime() / 1000;
			
			hdr.typeFlag = isDir ? TarHeader.LF_DIR : TarHeader.LF_NORMAL;
			
			hdr.linkName  = new StringBuilder(String.Empty);
			hdr.userName  = new StringBuilder(String.Empty);
			hdr.groupName = new StringBuilder(String.Empty);
			
			hdr.devMajor = 0;
			hdr.devMinor = 0;
		}
Пример #9
0
		/// <summary>
		/// Get the next entry in this tar archive. This will skip
		/// over any remaining data in the current entry, if there
		/// is one, and place the input stream at the header of the
		/// next entry, and read the header and instantiate a new
		/// TarEntry from the header bytes and return that entry.
		/// If there are no more entries in the archive, null will
		/// be returned to indicate that the end of the archive has
		/// been reached.
		/// </summary>
		/// <returns>
		/// The next TarEntry in the archive, or null.
		/// </returns>
		public TarEntry GetNextEntry()
		{
			if (this.hasHitEOF) {
				return null;
			}
			
			if (this.currentEntry != null) {
				SkipToNextEntry();
			}
			
			byte[] headerBuf = this.buffer.ReadBlock();
			
			if (headerBuf == null) {
				this.hasHitEOF = true;
			} else if (buffer.IsEOFBlock(headerBuf)) {
				this.hasHitEOF = true;
			}
			
			if (this.hasHitEOF) {
				this.currentEntry = null;
			} else {
				try {
					TarHeader header = new TarHeader();
					header.ParseBuffer(headerBuf);
					if ( !header.IsChecksumValid )
					{
						throw new TarException("Header checksum is invalid");
					}
					this.entryOffset = 0;
					this.entrySize = header.Size;
					
					StringBuilder longName = null;
					
					if (header.TypeFlag == TarHeader.LF_GNU_LONGNAME) {
						
						byte[] nameBuffer = new byte[TarBuffer.BlockSize];
						long numToRead = this.entrySize;
						
						longName = new StringBuilder();
						
						while (numToRead > 0) {
							int numRead = this.Read(nameBuffer, 0, (numToRead > nameBuffer.Length ? nameBuffer.Length : (int)numToRead));
							
							if (numRead == -1) {
								throw new InvalidHeaderException("Failed to read long name entry");
							}
							
							longName.Append(TarHeader.ParseName(nameBuffer, 0, numRead).ToString());
							numToRead -= numRead;
						}
						
						SkipToNextEntry();
						headerBuf = this.buffer.ReadBlock();
					} else if (header.TypeFlag == TarHeader.LF_GHDR) {  // POSIX global extended header 
						// Ignore things we dont understand completely for now
						SkipToNextEntry();
						headerBuf = this.buffer.ReadBlock();
					} else if (header.TypeFlag == TarHeader.LF_XHDR) {  // POSIX extended header
						// Ignore things we dont understand completely for now
						SkipToNextEntry();
						headerBuf = this.buffer.ReadBlock();
					} else if (header.TypeFlag == TarHeader.LF_GNU_VOLHDR) {
						// TODO: could show volume name when verbose
						SkipToNextEntry();
						headerBuf = this.buffer.ReadBlock();
					} else if (header.TypeFlag != TarHeader.LF_NORMAL && 
					           header.TypeFlag != TarHeader.LF_OLDNORM &&
					           header.TypeFlag != TarHeader.LF_DIR) {
						// Ignore things we dont understand completely for now
						SkipToNextEntry();
						headerBuf = this.buffer.ReadBlock();
					}
					
					if (this.entryFactory == null) {
						this.currentEntry = new TarEntry(headerBuf);
						if (longName != null) {
							currentEntry.Name = longName.ToString();
						}
					} else {
						this.currentEntry = this.entryFactory.CreateEntry(headerBuf);
					}
					
					// Magic was checked here for 'ustar' but there are multiple valid possibilities
					// so this is not done anymore.
					
					this.entryOffset = 0;
					
					// TODO: Review How do we resolve this discrepancy?!
					this.entrySize = this.currentEntry.Size;
				} catch (InvalidHeaderException ex) {
					this.entrySize = 0;
					this.entryOffset = 0;
					this.currentEntry = null;
					string errorText = string.Format("Bad header in record {0} block {1} {2}",
						buffer.CurrentRecord, buffer.CurrentBlock, ex.Message);
					throw new InvalidHeaderException(errorText);
				}
			}
			return this.currentEntry;
		}
Пример #10
0
        public TarEntry GetNextEntry()
        {
            if (this.hasHitEOF)
            {
                return(null);
            }

            if (this.currentEntry != null)
            {
                SkipToNextEntry();
            }

            byte[] headerBuf = this.buffer.ReadBlock();

            if (headerBuf == null)
            {
                this.hasHitEOF = true;
            }
            else if (TarBuffer.IsEndOfArchiveBlock(headerBuf))
            {
                this.hasHitEOF = true;
            }

            if (this.hasHitEOF)
            {
                this.currentEntry = null;
            }
            else
            {
                try {
                    TarHeader header = new TarHeader();
                    header.ParseBuffer(headerBuf);
                    if (!header.IsChecksumValid)
                    {
                        throw new TarException("Header checksum is invalid");
                    }
                    this.entryOffset = 0;
                    this.entrySize   = header.Size;

                    StringBuilder longName = null;

                    if (header.TypeFlag == TarHeader.LF_GNU_LONGNAME)
                    {
                        byte[] nameBuffer = new byte[TarBuffer.BlockSize];
                        long   numToRead  = this.entrySize;

                        longName = new StringBuilder();

                        while (numToRead > 0)
                        {
                            int numRead = this.Read(nameBuffer, 0, (numToRead > nameBuffer.Length ? nameBuffer.Length : (int)numToRead));

                            if (numRead == -1)
                            {
                                throw new InvalidHeaderException("Failed to read long name entry");
                            }

                            longName.Append(TarHeader.ParseName(nameBuffer, 0, numRead).ToString());
                            numToRead -= numRead;
                        }

                        SkipToNextEntry();
                        headerBuf = this.buffer.ReadBlock();
                    }
                    else if (header.TypeFlag == TarHeader.LF_GHDR)
                    {
                        SkipToNextEntry();
                        headerBuf = this.buffer.ReadBlock();
                    }
                    else if (header.TypeFlag == TarHeader.LF_XHDR)
                    {
                        SkipToNextEntry();
                        headerBuf = this.buffer.ReadBlock();
                    }
                    else if (header.TypeFlag == TarHeader.LF_GNU_VOLHDR)
                    {
                        SkipToNextEntry();
                        headerBuf = this.buffer.ReadBlock();
                    }
                    else if (header.TypeFlag != TarHeader.LF_NORMAL &&
                             header.TypeFlag != TarHeader.LF_OLDNORM &&
                             header.TypeFlag != TarHeader.LF_DIR)
                    {
                        SkipToNextEntry();
                        headerBuf = this.buffer.ReadBlock();
                    }

                    if (this.entryFactory == null)
                    {
                        this.currentEntry = new TarEntry(headerBuf);
                        if (longName != null)
                        {
                            currentEntry.Name = longName.ToString();
                        }
                    }
                    else
                    {
                        this.currentEntry = this.entryFactory.CreateEntry(headerBuf);
                    }


                    this.entryOffset = 0;

                    this.entrySize = this.currentEntry.Size;
                } catch (InvalidHeaderException ex) {
                    this.entrySize    = 0;
                    this.entryOffset  = 0;
                    this.currentEntry = null;
                    string errorText = string.Format("Bad header in record {0} block {1} {2}",
                                                     buffer.CurrentRecord, buffer.CurrentBlock, ex.Message);
                    throw new InvalidHeaderException(errorText);
                }
            }
            return(this.currentEntry);
        }
Пример #11
0
 private static void GetCheckSumOctalBytes(long value, byte[] buffer, int offset, int length)
 {
     TarHeader.GetOctalBytes(value, buffer, offset, length - 1);
 }
Пример #12
0
        public override bool Equals(object obj)
        {
            TarHeader tarHeader = obj as TarHeader;

            return(tarHeader != null && (this.name == tarHeader.name && this.mode == tarHeader.mode && this.UserId == tarHeader.UserId && this.GroupId == tarHeader.GroupId && this.Size == tarHeader.Size && this.ModTime == tarHeader.ModTime && this.Checksum == tarHeader.Checksum && this.TypeFlag == tarHeader.TypeFlag && this.LinkName == tarHeader.LinkName && this.Magic == tarHeader.Magic && this.Version == tarHeader.Version && this.UserName == tarHeader.UserName && this.GroupName == tarHeader.GroupName && this.DevMajor == tarHeader.DevMajor) && this.DevMinor == tarHeader.DevMinor);
        }
Пример #13
0
        /// <summary>
        /// Put an entry on the output stream. This writes the entry's
        /// header and positions the output stream for writing
        /// the contents of the entry. Once this method is called, the
        /// stream is ready for calls to write() to write the entry's
        /// contents. Once the contents are written, closeEntry()
        /// <B>MUST</B> be called to ensure that all buffered data
        /// is completely written to the output stream.
        /// </summary>
        /// <param name="entry">
        /// The TarEntry to be written to the archive.
        /// </param>
        public void PutNextEntry(TarEntry entry)
        {
            if (entry == null) {
                throw new ArgumentNullException(nameof(entry));
            }

            if (entry.TarHeader.Name.Length > TarHeader.NAMELEN) {
                var longHeader = new TarHeader();
                longHeader.TypeFlag = TarHeader.LF_GNU_LONGNAME;
                longHeader.Name = longHeader.Name + "././@LongLink";
                longHeader.Mode = 420;//644 by default
                longHeader.UserId = entry.UserId;
                longHeader.GroupId = entry.GroupId;
                longHeader.GroupName = entry.GroupName;
                longHeader.UserName = entry.UserName;
                longHeader.LinkName = "";
                longHeader.Size = entry.TarHeader.Name.Length + 1;  // Plus one to avoid dropping last char

                longHeader.WriteHeader(blockBuffer);
                buffer.WriteBlock(blockBuffer);  // Add special long filename header block

                int nameCharIndex = 0;

                while (nameCharIndex < entry.TarHeader.Name.Length + 1 /* we've allocated one for the null char, now we must make sure it gets written out */) {
                    Array.Clear(blockBuffer, 0, blockBuffer.Length);
                    TarHeader.GetAsciiBytes(entry.TarHeader.Name, nameCharIndex, this.blockBuffer, 0, TarBuffer.BlockSize); // This func handles OK the extra char out of string length
                    nameCharIndex += TarBuffer.BlockSize;
                    buffer.WriteBlock(blockBuffer);
                }
            }

            entry.WriteEntryHeader(blockBuffer);
            buffer.WriteBlock(blockBuffer);

            currBytes = 0;

            currSize = entry.IsDirectory ? 0 : entry.Size;
        }
Пример #14
0
 public TarEntry GetNextEntry()
 {
     //IL_00a6: Unknown result type (might be due to invalid IL or missing references)
     //IL_00ac: Expected O, but got Unknown
     if (hasHitEOF)
     {
         return(null);
     }
     if (currentEntry != null)
     {
         SkipToNextEntry();
     }
     byte[] array = tarBuffer.ReadBlock();
     if (array == null)
     {
         hasHitEOF = true;
     }
     else if (TarBuffer.IsEndOfArchiveBlock(array))
     {
         hasHitEOF = true;
     }
     if (hasHitEOF)
     {
         currentEntry = null;
     }
     else
     {
         try
         {
             TarHeader tarHeader = new TarHeader();
             tarHeader.ParseBuffer(array);
             if (!tarHeader.IsChecksumValid)
             {
                 throw new TarException("Header checksum is invalid");
             }
             entryOffset = 0L;
             entrySize   = tarHeader.Size;
             StringBuilder val = null;
             if (tarHeader.TypeFlag == 76)
             {
                 byte[] array2 = new byte[512];
                 long   num    = entrySize;
                 val = new StringBuilder();
                 while (num > 0)
                 {
                     int num2 = ((Stream)this).Read(array2, 0, (int)((num > array2.Length) ? array2.Length : num));
                     if (num2 == -1)
                     {
                         throw new InvalidHeaderException("Failed to read long name entry");
                     }
                     val.Append(((object)TarHeader.ParseName(array2, 0, num2)).ToString());
                     num -= num2;
                 }
                 SkipToNextEntry();
                 array = tarBuffer.ReadBlock();
             }
             else if (tarHeader.TypeFlag == 103)
             {
                 SkipToNextEntry();
                 array = tarBuffer.ReadBlock();
             }
             else if (tarHeader.TypeFlag == 120)
             {
                 SkipToNextEntry();
                 array = tarBuffer.ReadBlock();
             }
             else if (tarHeader.TypeFlag == 86)
             {
                 SkipToNextEntry();
                 array = tarBuffer.ReadBlock();
             }
             else if (tarHeader.TypeFlag != 48 && tarHeader.TypeFlag != 0 && tarHeader.TypeFlag != 53)
             {
                 SkipToNextEntry();
                 array = tarBuffer.ReadBlock();
             }
             if (entryFactory == null)
             {
                 currentEntry = new TarEntry(array);
                 if (val != null)
                 {
                     currentEntry.Name = ((object)val).ToString();
                 }
             }
             else
             {
                 currentEntry = entryFactory.CreateEntry(array);
             }
             entryOffset = 0L;
             entrySize   = currentEntry.Size;
         }
         catch (InvalidHeaderException ex)
         {
             entrySize    = 0L;
             entryOffset  = 0L;
             currentEntry = null;
             string message = $"Bad header in record {tarBuffer.CurrentRecord} block {tarBuffer.CurrentBlock} {((global::System.Exception)(object)ex).get_Message()}";
             throw new InvalidHeaderException(message);
         }
     }
     return(currentEntry);
 }
Пример #15
0
		/// <summary>
		/// Get the next entry in this tar archive. This will skip
		/// over any remaining data in the current entry, if there
		/// is one, and place the input stream at the header of the
		/// next entry, and read the header and instantiate a new
		/// TarEntry from the header bytes and return that entry.
		/// If there are no more entries in the archive, null will
		/// be returned to indicate that the end of the archive has
		/// been reached.
		/// </summary>
		/// <returns>
		/// The next TarEntry in the archive, or null.
		/// </returns>
		public TarEntry GetNextEntry()
		{
			if (this.hasHitEOF) 
			{
				return null;
			}
			
			if (this.currEntry != null) 
			{
            SkipToNextEntry();
			}
			
			byte[] headerBuf = this.buffer.ReadBlock();
			
			if (headerBuf == null) 
			{
				if (this.debug) 
				{
					//Console.WriteLine.WriteLine("READ NULL BLOCK");
				}
				
				this.hasHitEOF = true;
			} 
			else if (this.buffer.IsEOFBlock(headerBuf)) 
			{
				if (this.debug) 
				{
					//Console.WriteLine.WriteLine( "READ EOF BLOCK" );
				}
				
				this.hasHitEOF = true;
			}
			
			if (this.hasHitEOF) 
			{
				this.currEntry = null;
			} 
			else 
			{
				try 
				{
               TarHeader header = new TarHeader();
               header.ParseBuffer(headerBuf);
               this.entryOffset = 0;
               this.entrySize = (int)header.size;

               StringBuilder longName = null;

               if (header.typeFlag == TarHeader.LF_GNU_LONGNAME)
               {
                  Console.WriteLine("TarInputStream: Long name found '" + header.name + "' size = " + header.size); // DEBUG

                  byte[] nameBuffer = new byte[TarBuffer.BlockSize];

                  int numToRead = this.entrySize;

                  longName = new StringBuilder();

                  while (numToRead > 0)
                  {
                     int numRead = this.Read(nameBuffer, 0, (numToRead > nameBuffer.Length ? nameBuffer.Length : numToRead));
				
                     if (numRead == -1) 
                     {
                        throw new InvalidHeaderException("Failed to read long name entry");
                     }
				
                     longName.Append(TarHeader.ParseName(nameBuffer, 0, numRead).ToString());
                     numToRead -= numRead;
                  }

                  Console.WriteLine("TarInputStream: Long name is '" + longName.ToString()); // DEBUG

                  SkipToNextEntry();
                  headerBuf = this.buffer.ReadBlock();
               }
               else if (header.typeFlag == TarHeader.LF_GHDR) // POSIX global extended header
               {
                  // Ignore things we dont understand completely for now
                  SkipToNextEntry();
                  headerBuf = this.buffer.ReadBlock();
               }
               else if (header.typeFlag == TarHeader.LF_XHDR)     // POSIX extended header
               {
                  // Ignore things we dont understand completely for now
                  SkipToNextEntry();
                  headerBuf = this.buffer.ReadBlock();
               }
               else if (header.typeFlag == TarHeader.LF_GNU_VOLHDR)
               {
                  // TODO could show volume name when verbose?
                  SkipToNextEntry();
                  headerBuf = this.buffer.ReadBlock();
               }
               else if (header.typeFlag != TarHeader.LF_NORMAL
                  && header.typeFlag != TarHeader.LF_OLDNORM)
               {
                  // Ignore things we dont understand completely for now
                  SkipToNextEntry();
                  headerBuf = this.buffer.ReadBlock();
               }

               if (this.eFactory == null) 
					{
                  this.currEntry = new TarEntry(headerBuf);
                  if (longName != null)
                  {
                     this.currEntry.TarHeader.name.Length = 0;
                     this.currEntry.TarHeader.name.Append(longName.ToString());
                  }
					} 
					else 
					{
                  this.currEntry = this.eFactory.CreateEntry(headerBuf);
					}

					// TODO -jr- ustar is not the only magic possible by any means
               // tar, xtar, ... 
					if (!(headerBuf[257] == 'u' && headerBuf[258] == 's' && headerBuf[259] == 't' && headerBuf[260] == 'a' && headerBuf[261] == 'r')) 
					{
						throw new InvalidHeaderException("header magic is not 'ustar', but '" + headerBuf[257] + headerBuf[258] + headerBuf[259] + headerBuf[260] + headerBuf[261] + 
							"', or (dec) " + ((int)headerBuf[257]) + ", " + ((int)headerBuf[258]) + ", " + ((int)headerBuf[259]) + ", " + ((int)headerBuf[260]) + ", " + ((int)headerBuf[261]));
					}
					        
					if (this.debug) 
					{
						//Console.WriteLine.WriteLine("TarInputStream: SET CURRENTRY '" + this.currEntry.Name + "' size = " + this.currEntry.Size);
					}
			
					this.entryOffset = 0;
					
					// TODO REVIEW How do we resolve this discrepancy?!
					this.entrySize = (int) this.currEntry.Size;
				} 
				catch (InvalidHeaderException ex) 
				{
					this.entrySize = 0;
					this.entryOffset = 0;
					this.currEntry = null;
					throw new InvalidHeaderException("bad header in record " + this.buffer.GetCurrentBlockNum() + " block " + this.buffer.GetCurrentBlockNum() + ", " + ex.Message);
				}
			}
			return this.currEntry;
		}
Пример #16
0
		/// <summary>
		/// Put an entry on the output stream. This writes the entry's
		/// header and positions the output stream for writing
		/// the contents of the entry. Once this method is called, the
		/// stream is ready for calls to write() to write the entry's
		/// contents. Once the contents are written, closeEntry()
		/// <B>MUST</B> be called to ensure that all buffered data
		/// is completely written to the output stream.
		/// </summary>
		/// <param name="entry">
		/// The TarEntry to be written to the archive.
		/// </param>
		public void PutNextEntry(TarEntry entry)
		{
			if (entry.TarHeader.name.Length > TarHeader.NAMELEN) 
			{
            TarHeader longHeader = new TarHeader();
            longHeader.typeFlag = TarHeader.LF_GNU_LONGNAME;
            longHeader.name.Append("././@LongLink");
            longHeader.userId = 0;
            longHeader.groupId = 0;
            longHeader.groupName.Length = 0;
            longHeader.userName.Length = 0;
            longHeader.linkName.Length = 0;

            longHeader.size = entry.TarHeader.name.Length;

            Console.WriteLine("TarOutputStream: PutNext entry Long name found size = " + longHeader.size); // DEBUG

            longHeader.WriteHeader(this.blockBuf);
            this.buffer.WriteBlock(this.blockBuf);  // Add special long filename header block

            int nameCharIndex = 0;

            while (nameCharIndex < entry.TarHeader.name.Length)
            {
         		TarHeader.GetNameBytes(entry.TarHeader.name, nameCharIndex, this.blockBuf, 0, TarBuffer.BlockSize);
               nameCharIndex += TarBuffer.BlockSize;
               this.buffer.WriteBlock(this.blockBuf);
            }
			}
			
			entry.WriteEntryHeader(this.blockBuf);
			this.buffer.WriteBlock(this.blockBuf);
			
			this.currBytes = 0;
			
			this.currSize = entry.IsDirectory ? 0 : (int)entry.Size;
		}
Пример #17
0
 /// <summary>
 /// Construct an entry from an archive's header bytes. File is set
 /// to null.
 /// </summary>
 /// <param name = "headerBuffer">
 /// The header bytes from a tar archive entry.
 /// </param>
 /// <param name = "nameEncoding">
 /// The <see cref="Encoding"/> used for the Name fields, or null for ASCII only
 /// </param>
 public TarEntry(byte[] headerBuffer, Encoding nameEncoding)
 {
     header = new TarHeader();
     header.ParseBuffer(headerBuffer, nameEncoding);
 }
Пример #18
0
		/// <summary>
		/// Initialization code common to all pseudo constructors.
		/// </summary>
		void Initialize()
		{
			this.file   = null;
			this.header = new TarHeader();
		}
Пример #19
0
        /// <summary>
        /// Parse TarHeader information from a header buffer.
        /// </summary>
        /// <param name = "header">
        /// The tar entry header buffer to get information from.
        /// </param>
        public void ParseBuffer(byte[] header)
        {
            if (header == null)
            {
                throw new ArgumentNullException(nameof(header));
            }

            int offset = 0;

            name    = ParseName(header, offset, NAMELEN).ToString();
            offset += NAMELEN;

            mode    = (int)ParseOctal(header, offset, MODELEN);
            offset += MODELEN;

            UserId  = (int)ParseOctal(header, offset, UIDLEN);
            offset += UIDLEN;

            GroupId = (int)ParseOctal(header, offset, GIDLEN);
            offset += GIDLEN;

            Size    = ParseBinaryOrOctal(header, offset, SIZELEN);
            offset += SIZELEN;

            ModTime = GetDateTimeFromCTime(ParseOctal(header, offset, MODTIMELEN));
            offset += MODTIMELEN;

            checksum = (int)ParseOctal(header, offset, CHKSUMLEN);
            offset  += CHKSUMLEN;

            TypeFlag = header[offset++];

            LinkName = ParseName(header, offset, NAMELEN).ToString();
            offset  += NAMELEN;

            Magic   = ParseName(header, offset, MAGICLEN).ToString();
            offset += MAGICLEN;

            if (Magic == "ustar")
            {
                Version = ParseName(header, offset, VERSIONLEN).ToString();
                offset += VERSIONLEN;

                UserName = ParseName(header, offset, UNAMELEN).ToString();
                offset  += UNAMELEN;

                GroupName = ParseName(header, offset, GNAMELEN).ToString();
                offset   += GNAMELEN;

                DevMajor = (int)ParseOctal(header, offset, DEVLEN);
                offset  += DEVLEN;

                DevMinor = (int)ParseOctal(header, offset, DEVLEN);
                offset  += DEVLEN;

                string prefix = ParseName(header, offset, PREFIXLEN).ToString();
                if (!string.IsNullOrEmpty(prefix))
                {
                    Name = prefix + '/' + Name;
                }
            }

            isChecksumValid = Checksum == TarHeader.MakeCheckSum(header);
        }
Пример #20
0
 /// <summary>
 /// Convenience method that will modify an entry's name directly
 /// in place in an entry header buffer byte array.
 /// </summary>
 /// <param name="buffer">
 /// The buffer containing the entry header to modify.
 /// </param>
 /// <param name="newName">
 /// The new name to place into the header buffer.
 /// </param>
 static public void AdjustEntryName(byte[] buffer, string newName)
 {
     TarHeader.GetNameBytes(newName, buffer, 0, TarHeader.NAMELEN);
 }
Пример #21
0
        public override bool Equals(object obj)
        {
            TarHeader header = obj as TarHeader;

            return((header != null) && ((((((this.name == header.name) && (this.mode == header.mode)) && ((this.UserId == header.UserId) && (this.GroupId == header.GroupId))) && (((this.Size == header.Size) && (this.ModTime == header.ModTime)) && ((this.Checksum == header.Checksum) && (this.TypeFlag == header.TypeFlag)))) && ((((this.LinkName == header.LinkName) && (this.Magic == header.Magic)) && ((this.Version == header.Version) && (this.UserName == header.UserName))) && ((this.GroupName == header.GroupName) && (this.DevMajor == header.DevMajor)))) && (this.DevMinor == header.DevMinor)));
        }
Пример #22
0
		/// <summary>
		/// Initialise a default instance of <see cref="TarEntry"/>.
		/// </summary>
		private TarEntry()
		{
			header = new TarHeader();
		}
Пример #23
0
 public TarEntry GetNextEntry()
 {
     if (this.hasHitEOF)
     {
         return(null);
     }
     if (this.currentEntry != null)
     {
         this.SkipToNextEntry();
     }
     byte[] block = this.tarBuffer.ReadBlock();
     if (block == null)
     {
         this.hasHitEOF = true;
     }
     else if (TarBuffer.IsEndOfArchiveBlock(block))
     {
         this.hasHitEOF = true;
     }
     if (this.hasHitEOF)
     {
         this.currentEntry = null;
     }
     else
     {
         try
         {
             TarHeader header = new TarHeader();
             header.ParseBuffer(block);
             if (!header.IsChecksumValid)
             {
                 throw new TarException("Header checksum is invalid");
             }
             this.entryOffset = 0L;
             this.entrySize   = header.Size;
             StringBuilder builder = null;
             if (header.TypeFlag == 0x4c)
             {
                 byte[] buffer    = new byte[0x200];
                 long   entrySize = this.entrySize;
                 builder = new StringBuilder();
                 while (entrySize > 0L)
                 {
                     int length = this.Read(buffer, 0, (entrySize > buffer.Length) ? buffer.Length : ((int)entrySize));
                     if (length == -1)
                     {
                         throw new InvalidHeaderException("Failed to read long name entry");
                     }
                     builder.Append(TarHeader.ParseName(buffer, 0, length).ToString());
                     entrySize -= length;
                 }
                 this.SkipToNextEntry();
                 block = this.tarBuffer.ReadBlock();
             }
             else if (header.TypeFlag == 0x67)
             {
                 this.SkipToNextEntry();
                 block = this.tarBuffer.ReadBlock();
             }
             else if (header.TypeFlag == 120)
             {
                 this.SkipToNextEntry();
                 block = this.tarBuffer.ReadBlock();
             }
             else if (header.TypeFlag == 0x56)
             {
                 this.SkipToNextEntry();
                 block = this.tarBuffer.ReadBlock();
             }
             else if (((header.TypeFlag != 0x30) && (header.TypeFlag != 0)) && (header.TypeFlag != 0x35))
             {
                 this.SkipToNextEntry();
                 block = this.tarBuffer.ReadBlock();
             }
             if (this.entryFactory == null)
             {
                 this.currentEntry = new TarEntry(block);
                 if (builder != null)
                 {
                     this.currentEntry.Name = builder.ToString();
                 }
             }
             else
             {
                 this.currentEntry = this.entryFactory.CreateEntry(block);
             }
             this.entryOffset = 0L;
             this.entrySize   = this.currentEntry.Size;
         }
         catch (InvalidHeaderException exception)
         {
             this.entrySize    = 0L;
             this.entryOffset  = 0L;
             this.currentEntry = null;
             throw new InvalidHeaderException(string.Format("Bad header in record {0} block {1} {2}", this.tarBuffer.CurrentRecord, this.tarBuffer.CurrentBlock, exception.Message));
         }
     }
     return(this.currentEntry);
 }
Пример #24
0
        /// <summary>
        /// Get the next entry in this tar archive. This will skip
        /// over any remaining data in the current entry, if there
        /// is one, and place the input stream at the header of the
        /// next entry, and read the header and instantiate a new
        /// TarEntry from the header bytes and return that entry.
        /// If there are no more entries in the archive, null will
        /// be returned to indicate that the end of the archive has
        /// been reached.
        /// </summary>
        /// <returns>
        /// The next TarEntry in the archive, or null.
        /// </returns>
        public TarEntry GetNextEntry()
        {
            if (this.hasHitEOF)
            {
                return(null);
            }

            if (this.currentEntry != null)
            {
                SkipToNextEntry();
            }

            byte[] headerBuf = this.buffer.ReadBlock();

            if (headerBuf == null)
            {
                this.hasHitEOF = true;
            }
            else if (buffer.IsEOFBlock(headerBuf))
            {
                this.hasHitEOF = true;
            }

            if (this.hasHitEOF)
            {
                this.currentEntry = null;
            }
            else
            {
                try {
                    TarHeader header = new TarHeader();
                    header.ParseBuffer(headerBuf);
                    if (!header.IsChecksumValid)
                    {
                        throw new TarException("Header checksum is invalid");
                    }
                    this.entryOffset = 0;
                    this.entrySize   = header.Size;

                    StringBuilder longName = null;

                    if (header.TypeFlag == TarHeader.LF_GNU_LONGNAME)
                    {
                        byte[] nameBuffer = new byte[TarBuffer.BlockSize];
                        long   numToRead  = this.entrySize;

                        longName = new StringBuilder();

                        while (numToRead > 0)
                        {
                            int numRead = this.Read(nameBuffer, 0, (numToRead > nameBuffer.Length ? nameBuffer.Length : (int)numToRead));

                            if (numRead == -1)
                            {
                                throw new InvalidHeaderException("Failed to read long name entry");
                            }

                            longName.Append(TarHeader.ParseName(nameBuffer, 0, numRead).ToString());
                            numToRead -= numRead;
                        }

                        SkipToNextEntry();
                        headerBuf = this.buffer.ReadBlock();
                    }
                    else if (header.TypeFlag == TarHeader.LF_GHDR)                          // POSIX global extended header
                    // Ignore things we dont understand completely for now
                    {
                        SkipToNextEntry();
                        headerBuf = this.buffer.ReadBlock();
                    }
                    else if (header.TypeFlag == TarHeader.LF_XHDR)                          // POSIX extended header
                    // Ignore things we dont understand completely for now
                    {
                        SkipToNextEntry();
                        headerBuf = this.buffer.ReadBlock();
                    }
                    else if (header.TypeFlag == TarHeader.LF_GNU_VOLHDR)
                    {
                        // TODO: could show volume name when verbose
                        SkipToNextEntry();
                        headerBuf = this.buffer.ReadBlock();
                    }
                    else if (header.TypeFlag != TarHeader.LF_NORMAL &&
                             header.TypeFlag != TarHeader.LF_OLDNORM &&
                             header.TypeFlag != TarHeader.LF_DIR)
                    {
                        // Ignore things we dont understand completely for now
                        SkipToNextEntry();
                        headerBuf = this.buffer.ReadBlock();
                    }

                    if (this.entryFactory == null)
                    {
                        this.currentEntry = new TarEntry(headerBuf);
                        if (longName != null)
                        {
                            currentEntry.Name = longName.ToString();
                        }
                    }
                    else
                    {
                        this.currentEntry = this.entryFactory.CreateEntry(headerBuf);
                    }

                    // Magic was checked here for 'ustar' but there are multiple valid possibilities
                    // so this is not done anymore.

                    this.entryOffset = 0;

                    // TODO: Review How do we resolve this discrepancy?!
                    this.entrySize = this.currentEntry.Size;
                } catch (InvalidHeaderException ex) {
                    this.entrySize    = 0;
                    this.entryOffset  = 0;
                    this.currentEntry = null;
                    string errorText = string.Format("Bad header in record {0} block {1} {2}",
                                                     buffer.CurrentRecord, buffer.CurrentBlock, ex.Message);
                    throw new InvalidHeaderException(errorText);
                }
            }
            return(this.currentEntry);
        }
Пример #25
0
        /// <summary>
        /// Convenience method that will modify an entry's name directly
        /// in place in an entry header buffer byte array.
        /// </summary>
        /// <param name="buffer">
        /// The buffer containing the entry header to modify.
        /// </param>
        /// <param name="newName">
        /// The new name to place into the header buffer.
        /// </param>
        static public void AdjustEntryName(byte[] buffer, string newName)
        {
            int offset = 0;

            TarHeader.GetNameBytes(newName, buffer, offset, TarHeader.NAMELEN);
        }
Пример #26
0
        /// <summary>
        /// Fill in a TarHeader given only the entry's name.
        /// </summary>
        /// <param name="hdr">
        /// The TarHeader to fill in.
        /// </param>
        /// <param name="name">
        /// The tar entry name.
        /// </param>
        public void NameTarHeader(TarHeader hdr, string name)
        {
            bool isDir = name.EndsWith("/");

            hdr.checkSum = 0;

            hdr.name = new StringBuilder(name);
            hdr.mode = isDir ? 1003 : 33216;
            hdr.userId   = 0;
            hdr.groupId  = 0;
            hdr.size     = 0;
            hdr.checkSum = 0;

            hdr.modTime  = DateTime.UtcNow;

            hdr.typeFlag = isDir ? TarHeader.LF_DIR : TarHeader.LF_NORMAL;

            hdr.linkName  = new StringBuilder(String.Empty);
            hdr.userName  = new StringBuilder(String.Empty);
            hdr.groupName = new StringBuilder(String.Empty);

            hdr.devMajor = 0;
            hdr.devMinor = 0;
        }
Пример #27
0
 /// <summary>
 /// Initialise a default instance of <see cref="TarEntry"/>.
 /// </summary>
 private TarEntry()
 {
     header = new TarHeader();
 }
Пример #28
0
		/// <summary>
		/// Fill in a TarHeader with information from a File.
		/// </summary>
		/// <param name="header">
		/// The TarHeader to fill in.
		/// </param>
		/// <param name="file">
		/// The file from which to get the header information.
		/// </param>
		public void GetFileTarHeader(TarHeader header, string file)
		{
			if ( header == null ) {
				throw new ArgumentNullException("header");
			}

			if ( file == null ) {
				throw new ArgumentNullException("file");
			}

			this.file = file;

            header.LinkName = String.Empty;
            /// <remarks>
            /// Needed to remove directory tree for ODIN sanity
            /// header.Name = name;
            /// </remarks>
            header.Name = Path.GetFileName(file);
			
			if (Directory.Exists(file)) {
				header.Mode     = 1003; // Magic number for security access for a UNIX filesystem
				header.TypeFlag = TarHeader.LF_DIR;
				if ( (header.Name.Length == 0) || header.Name[header.Name.Length - 1] != '/') {
					header.Name = header.Name + "/";
				}
				
				header.Size     = 0;
			} else {
				header.Mode     = 33216; // Magic number for security access for a UNIX filesystem
				header.TypeFlag = TarHeader.LF_NORMAL;
				header.Size     = new FileInfo(file.Replace('/', Path.DirectorySeparatorChar)).Length;
			}

			header.ModTime = System.IO.File.GetLastWriteTime(file.Replace('/', Path.DirectorySeparatorChar)).ToUniversalTime();
			header.DevMajor = 0;
			header.DevMinor = 0;
		}
Пример #29
0
 /// <summary>
 /// Construct an entry from an archive's header bytes. File is set
 /// to null.
 /// </summary>
 /// <param name = "headerBuffer">
 /// The header bytes from a tar archive entry.
 /// </param>
 public TarEntry(byte[] headerBuffer)
 {
     header = new TarHeader();
     header.ParseBuffer(headerBuffer);
 }
Пример #30
0
        public void GetFileTarHeader(TarHeader header, string file)
        {
            if ( header == null ) {
                throw new ArgumentNullException("header");
            }

            if ( file == null ) {
                throw new ArgumentNullException("file");
            }

            this.file = file;

            string name = file;

            #if !NETCF_1_0 && !NETCF_2_0

            if (name.IndexOf(Environment.CurrentDirectory) == 0) {
                name = name.Substring(Environment.CurrentDirectory.Length);
            }
            #endif

            name = name.Replace(Path.DirectorySeparatorChar, '/');

            while (name.StartsWith("/")) {
                name = name.Substring(1);
            }

            header.LinkName = String.Empty;
            header.Name     = name;

            if (Directory.Exists(file)) {
                header.Mode     = 1003;
                header.TypeFlag = TarHeader.LF_DIR;
                if ( (header.Name.Length == 0) || header.Name[header.Name.Length - 1] != '/') {
                    header.Name = header.Name + "/";
                }

                header.Size     = 0;
            } else {
                header.Mode     = 33216;
                header.TypeFlag = TarHeader.LF_NORMAL;
                header.Size     = new FileInfo(file.Replace('/', Path.DirectorySeparatorChar)).Length;
            }

            header.ModTime = System.IO.File.GetLastWriteTime(file.Replace('/', Path.DirectorySeparatorChar)).ToUniversalTime();
            header.DevMajor = 0;
            header.DevMinor = 0;
        }
Пример #31
0
 /// <summary>
 /// Initialization code common to all pseudo constructors.
 /// </summary>
 void Initialize()
 {
     this.file   = null;
     this.header = new TarHeader();
 }
Пример #32
0
		/// <summary>
		/// Fill in a TarHeader given only the entry's name.
		/// </summary>
		/// <param name="hdr">
		/// The TarHeader to fill in.
		/// </param>
		/// <param name="name">
		/// The tar entry name.
		/// </param>
		public void NameTarHeader(TarHeader hdr, string name)
		{
			bool isDir = name.EndsWith("/");
			
			hdr.Name = name;
			hdr.Mode = isDir ? 1003 : 33216;
			hdr.UserId   = 0;
			hdr.GroupId  = 0;
			hdr.Size     = 0;
			
			hdr.ModTime  = DateTime.UtcNow;
			
			hdr.TypeFlag = isDir ? TarHeader.LF_DIR : TarHeader.LF_NORMAL;
			
			hdr.LinkName  = String.Empty;
			hdr.UserName  = String.Empty;
			hdr.GroupName = String.Empty;
			
			hdr.DevMajor = 0;
			hdr.DevMinor = 0;
		}
Пример #33
0
        /// <summary>
        /// Convenience method that will modify an entry's name directly
        /// in place in an entry header buffer byte array.
        /// </summary>
        /// <param name="outbuf">
        /// The buffer containing the entry header to modify.
        /// </param>
        /// <param name="newName">
        /// The new name to place into the header buffer.
        /// </param>
        public void AdjustEntryName(byte[] outbuf, string newName)
        {
            int offset = 0;

            offset = TarHeader.GetNameBytes(new StringBuilder(newName), outbuf, offset, TarHeader.NAMELEN);
        }
Пример #34
0
		/// <summary>
		/// Put an entry on the output stream. This writes the entry's
		/// header and positions the output stream for writing
		/// the contents of the entry. Once this method is called, the
		/// stream is ready for calls to write() to write the entry's
		/// contents. Once the contents are written, closeEntry()
		/// <B>MUST</B> be called to ensure that all buffered data
		/// is completely written to the output stream.
		/// </summary>
		/// <param name="entry">
		/// The TarEntry to be written to the archive.
		/// </param>
		public void PutNextEntry(TarEntry entry)
		{
			if ( entry == null ) {
				throw new ArgumentNullException("entry");
			}

			if (entry.TarHeader.Name.Length >= TarHeader.NAMELEN) {
				TarHeader longHeader = new TarHeader();
				longHeader.TypeFlag = TarHeader.LF_GNU_LONGNAME;
				longHeader.Name = longHeader.Name + "././@LongLink";
				longHeader.UserId = 0;
				longHeader.GroupId = 0;
				longHeader.GroupName = "";
				longHeader.UserName = "";
				longHeader.LinkName = "";
                longHeader.Size = entry.TarHeader.Name.Length;

				longHeader.WriteHeader(blockBuffer);
				buffer.WriteBlock(blockBuffer);  // Add special long filename header block

				int nameCharIndex = 0;

				while (nameCharIndex < entry.TarHeader.Name.Length) {
					Array.Clear(blockBuffer, 0, blockBuffer.Length);
					TarHeader.GetAsciiBytes(entry.TarHeader.Name, nameCharIndex, this.blockBuffer, 0, TarBuffer.BlockSize);
					nameCharIndex += TarBuffer.BlockSize;
					buffer.WriteBlock(blockBuffer);
				}
			}
			
			entry.WriteEntryHeader(blockBuffer);
			buffer.WriteBlock(blockBuffer);
			
			currBytes = 0;
			
			currSize = entry.IsDirectory ? 0 : entry.Size;
		}
Пример #35
0
        /// <summary>
        /// Fill in a TarHeader with information from a File.
        /// </summary>
        /// <param name="hdr">
        /// The TarHeader to fill in.
        /// </param>
        /// <param name="file">
        /// The file from which to get the header information.
        /// </param>
        public void GetFileTarHeader(TarHeader hdr, string file)
        {
            this.file = file;

            // bugfix from torhovl from #D forum:
            string name = file;

            // -jr- 23-Jan-2004 HAK HAK HAK, GnuTar allows device names in path where the name is not local to the current directory
            if (Environment.CurrentDirectory == Path.GetDirectoryName(name))
            {
                name = Path.GetFileName(name);
            }

            /*
             *       if (Path.DirectorySeparatorChar == '\\')
             *                      {  // check if the OS is Windows
             *                              // Strip off drive letters!
             *                              if (name.Length > 2)
             *                              {
             *                                      char ch1 = name[0];
             *                                      char ch2 = name[1];
             *
             *                                      if (ch2 == ':' && Char.IsLetter(ch1))
             *                                      {
             *                                              name = name.Substring(2);
             *                                      }
             *                              }
             *                      }
             */

            name = name.Replace(Path.DirectorySeparatorChar, '/').ToLower();

            // No absolute pathnames
            // Windows (and Posix?) paths can start with UNC style "\\NetworkDrive\",
            // so we loop on starting /'s.
            while (name.StartsWith("/"))
            {
                name = name.Substring(1);
            }

            hdr.linkName = new StringBuilder(String.Empty);
            hdr.name     = new StringBuilder(name);

            if (Directory.Exists(file))
            {
                hdr.mode     = 1003; // 01753 -jr- no octal constants!! 040755; // Magic number for security access for a UNIX filesystem
                hdr.typeFlag = TarHeader.LF_DIR;
                if (hdr.name.Length == 0 || hdr.name[hdr.name.Length - 1] != '/')
                {
                    hdr.name.Append("/");
                }

                hdr.size = 0;
            }
            else
            {
                hdr.mode     = 33216; // 0100700 -jr-  // 0100644; // Magic number for security access for a UNIX filesystem
                hdr.typeFlag = TarHeader.LF_NORMAL;
                hdr.size     = new FileInfo(file.Replace('/', Path.DirectorySeparatorChar)).Length;
            }

            // UNDONE When File lets us get the userName, use it!
            hdr.modTime  = System.IO.File.GetLastWriteTimeUtc(file.Replace('/', Path.DirectorySeparatorChar)); // -jr- Unix times are in UTC
            hdr.checkSum = 0;
            hdr.devMajor = 0;
            hdr.devMinor = 0;
        }
Пример #36
0
 public TarEntry(TarHeader header)
 {
    file = null;
    this.header = header;
 }
Пример #37
0
        /// <summary>
        /// Get the next entry in this tar archive. This will skip
        /// over any remaining data in the current entry, if there
        /// is one, and place the input stream at the header of the
        /// next entry, and read the header and instantiate a new
        /// TarEntry from the header bytes and return that entry.
        /// If there are no more entries in the archive, null will
        /// be returned to indicate that the end of the archive has
        /// been reached.
        /// </summary>
        /// <returns>
        /// The next TarEntry in the archive, or null.
        /// </returns>
        public TarEntry GetNextEntry()
        {
            if (this.hasHitEOF)
            {
                return(null);
            }

            if (this.currEntry != null)
            {
                SkipToNextEntry();
            }

            byte[] headerBuf = this.buffer.ReadBlock();

            if (headerBuf == null)
            {
                if (this.debug)
                {
                    //Console.WriteLine.WriteLine("READ NULL BLOCK");
                }

                this.hasHitEOF = true;
            }
            else if (this.buffer.IsEOFBlock(headerBuf))
            {
                if (this.debug)
                {
                    //Console.WriteLine.WriteLine( "READ EOF BLOCK" );
                }

                this.hasHitEOF = true;
            }

            if (this.hasHitEOF)
            {
                this.currEntry = null;
            }
            else
            {
                try {
                    TarHeader header = new TarHeader();
                    header.ParseBuffer(headerBuf);
                    this.entryOffset = 0;
                    this.entrySize   = (int)header.size;

                    StringBuilder longName = null;

                    if (header.typeFlag == TarHeader.LF_GNU_LONGNAME)
                    {
                        byte[] nameBuffer = new byte[TarBuffer.BlockSize];

                        int numToRead = this.entrySize;

                        longName = new StringBuilder();

                        while (numToRead > 0)
                        {
                            int numRead = this.Read(nameBuffer, 0, (numToRead > nameBuffer.Length ? nameBuffer.Length : numToRead));

                            if (numRead == -1)
                            {
                                throw new InvalidHeaderException("Failed to read long name entry");
                            }

                            longName.Append(TarHeader.ParseName(nameBuffer, 0, numRead).ToString());
                            numToRead -= numRead;
                        }

                        SkipToNextEntry();
                        headerBuf = this.buffer.ReadBlock();
                    }
                    else if (header.typeFlag == TarHeader.LF_GHDR)                          // POSIX global extended header
                    // Ignore things we dont understand completely for now
                    {
                        SkipToNextEntry();
                        headerBuf = this.buffer.ReadBlock();
                    }
                    else if (header.typeFlag == TarHeader.LF_XHDR)                          // POSIX extended header
                    // Ignore things we dont understand completely for now
                    {
                        SkipToNextEntry();
                        headerBuf = this.buffer.ReadBlock();
                    }
                    else if (header.typeFlag == TarHeader.LF_GNU_VOLHDR)
                    {
                        // TODO  could show volume name when verbose?
                        SkipToNextEntry();
                        headerBuf = this.buffer.ReadBlock();
                    }
                    else if (header.typeFlag != TarHeader.LF_NORMAL &&
                             header.typeFlag != TarHeader.LF_OLDNORM &&
                             header.typeFlag != TarHeader.LF_DIR)
                    {
                        // Ignore things we dont understand completely for now
                        SkipToNextEntry();
                        headerBuf = this.buffer.ReadBlock();
                    }

                    if (this.eFactory == null)
                    {
                        this.currEntry = new TarEntry(headerBuf);
                        if (longName != null)
                        {
                            this.currEntry.TarHeader.name.Length = 0;
                            this.currEntry.TarHeader.name.Append(longName.ToString());
                        }
                    }
                    else
                    {
                        this.currEntry = this.eFactory.CreateEntry(headerBuf);
                    }

                    // TODO  ustar is not the only magic possible by any means
                    // tar, xtar, ...
                    if (!(headerBuf[257] == 'u' && headerBuf[258] == 's' && headerBuf[259] == 't' && headerBuf[260] == 'a' && headerBuf[261] == 'r'))
                    {
                        throw new InvalidHeaderException("header magic is not 'ustar', but '" + headerBuf[257] + headerBuf[258] + headerBuf[259] + headerBuf[260] + headerBuf[261] +
                                                         "', or (dec) " + ((int)headerBuf[257]) + ", " + ((int)headerBuf[258]) + ", " + ((int)headerBuf[259]) + ", " + ((int)headerBuf[260]) + ", " + ((int)headerBuf[261]));
                    }

                    if (this.debug)
                    {
                        //Console.WriteLine.WriteLine("TarInputStream: SET CURRENTRY '" + this.currEntry.Name + "' size = " + this.currEntry.Size);
                    }

                    this.entryOffset = 0;

                    // TODO  Review How do we resolve this discrepancy?!
                    this.entrySize = (int)this.currEntry.Size;
                } catch (InvalidHeaderException ex) {
                    this.entrySize   = 0;
                    this.entryOffset = 0;
                    this.currEntry   = null;
                    throw new InvalidHeaderException("bad header in record " + this.buffer.GetCurrentBlockNum() + " block " + this.buffer.GetCurrentBlockNum() + ", " + ex.Message);
                }
            }
            return(this.currEntry);
        }
Пример #38
0
		/// <summary>
		/// Fill in a TarHeader with information from a File.
		/// </summary>
		/// <param name="hdr">
		/// The TarHeader to fill in.
		/// </param>
		/// <param name="file">
		/// The file from which to get the header information.
		/// </param>
		public void GetFileTarHeader(TarHeader hdr, string file)
		{
			this.file = file;

			// bugfix from torhovl from #D forum:
			string name = file;

         // -jr- 23-Jan-2004 HAK HAK HAK, GnuTar allows device names in path where the name is not local to the current directory
         if (Environment.CurrentDirectory == Path.GetDirectoryName(name))
         {
            name = Path.GetFileName(name);
         }
/*			
         if (Path.DirectorySeparatorChar == '\\') 
			{  // check if the OS is Windows
				// Strip off drive letters!
				if (name.Length > 2) 
				{
					char ch1 = name[0];
					char ch2 = name[1];
					
					if (ch2 == ':' && Char.IsLetter(ch1)) 
					{
						name = name.Substring(2);
					}
				}
			}
*/
			
			name = name.Replace(Path.DirectorySeparatorChar, '/').ToLower();

			// No absolute pathnames
			// Windows (and Posix?) paths can start with UNC style "\\NetworkDrive\",
			// so we loop on starting /'s.
			while (name.StartsWith("/")) {
				name = name.Substring(1);
			}

			hdr.linkName = new StringBuilder(String.Empty);
			hdr.name     = new StringBuilder(name);
			
			if (Directory.Exists(file)) {
				hdr.mode     = 1003; // 01753 -jr- no octal constants!! 040755; // Magic number for security access for a UNIX filesystem
				hdr.typeFlag = TarHeader.LF_DIR;
				if (hdr.name.Length == 0 || hdr.name[hdr.name.Length - 1] != '/') {
					hdr.name.Append("/");
				}
				
				hdr.size     = 0;
			} else {
				hdr.mode     = 33216; // 0100700 -jr-  // 0100644; // Magic number for security access for a UNIX filesystem
				hdr.typeFlag = TarHeader.LF_NORMAL;
				hdr.size     = new FileInfo(file.Replace('/', Path.DirectorySeparatorChar)).Length;
			}
			
			// UNDONE When File lets us get the userName, use it!
         hdr.modTime = System.IO.File.GetLastWriteTimeUtc(file.Replace('/', Path.DirectorySeparatorChar)); // -jr- Unix times are in UTC
         hdr.checkSum = 0;
			hdr.devMajor = 0;
			hdr.devMinor = 0;
		}
Пример #39
0
 /// <summary>
 /// Construct a TarEntry using the <paramref name="header">header</paramref> provided
 /// </summary>
 /// <param name="header">Header details for entry</param>
 public TarEntry(TarHeader header)
 {
     file        = null;
     this.header = header;
 }
Пример #40
0
        /// <summary>
        /// Fill in a TarHeader with information from a File.
        /// </summary>
        /// <param name="header">
        /// The TarHeader to fill in.
        /// </param>
        /// <param name="file">
        /// The file from which to get the header information.
        /// </param>
        public void GetFileTarHeader(TarHeader header, string file)
        {
            if (header == null) {
                throw new ArgumentNullException("header");
            }

            if (file == null) {
                throw new ArgumentNullException("file");
            }

            this.file = file;

            // bugfix from torhovl from #D forum:
            string name = file;

            // 23-Jan-2004 GnuTar allows device names in path where the name is not local to the current directory
            if (name.IndexOf(Environment.CurrentDirectory, StringComparison.Ordinal) == 0) {
                name = name.Substring(Environment.CurrentDirectory.Length);
            }

            /*
                        if (Path.DirectorySeparatorChar == '\\')
                        {
                            // check if the OS is Windows
                            // Strip off drive letters!
                            if (name.Length > 2)
                            {
                                char ch1 = name[0];
                                char ch2 = name[1];

                                if (ch2 == ':' && Char.IsLetter(ch1))
                                {
                                    name = name.Substring(2);
                                }
                            }
                        }
            */

            name = name.Replace(Path.DirectorySeparatorChar, '/');

            // No absolute pathnames
            // Windows (and Posix?) paths can start with UNC style "\\NetworkDrive\",
            // so we loop on starting /'s.
            while (name.StartsWith("/", StringComparison.Ordinal)) {
                name = name.Substring(1);
            }

            header.LinkName = String.Empty;
            header.Name = name;

            if (Directory.Exists(file)) {
                header.Mode = 1003; // Magic number for security access for a UNIX filesystem
                header.TypeFlag = TarHeader.LF_DIR;
                if ((header.Name.Length == 0) || header.Name[header.Name.Length - 1] != '/') {
                    header.Name = header.Name + "/";
                }

                header.Size = 0;
            } else {
                header.Mode = 33216; // Magic number for security access for a UNIX filesystem
                header.TypeFlag = TarHeader.LF_NORMAL;
                header.Size = new FileInfo(file.Replace('/', Path.DirectorySeparatorChar)).Length;
            }

            header.ModTime = System.IO.File.GetLastWriteTime(file.Replace('/', Path.DirectorySeparatorChar)).ToUniversalTime();
            header.DevMajor = 0;
            header.DevMinor = 0;
        }
Пример #41
0
 /// <summary>
 /// Initialization code common to all pseudo constructors.
 /// </summary>
 void Initialize()
 {
     file   = null;
     header = new TarHeader();
 }
Пример #42
0
		public void HeaderEquality()
		{
			TarHeader h1 = new TarHeader();
			TarHeader h2 = new TarHeader();

			Assert.IsTrue(h1.Equals(h2));

			h1.Name = "ABCDEFG";
			Assert.IsFalse(h1.Equals(h2));
			h2.Name = h1.Name;
			Assert.IsTrue(h1.Equals(h2));

			h1.Mode = 33188;
			Assert.IsFalse(h1.Equals(h2));
			h2.Mode = h1.Mode;
			Assert.IsTrue(h1.Equals(h2));

			h1.UserId = 654;
			Assert.IsFalse(h1.Equals(h2));
			h2.UserId = h1.UserId;
			Assert.IsTrue(h1.Equals(h2));

			h1.GroupId = 654;
			Assert.IsFalse(h1.Equals(h2));
			h2.GroupId = h1.GroupId;
			Assert.IsTrue(h1.Equals(h2));

			h1.Size = 654;
			Assert.IsFalse(h1.Equals(h2));
			h2.Size = h1.Size;
			Assert.IsTrue(h1.Equals(h2));

			h1.ModTime = DateTime.Now;
			Assert.IsFalse(h1.Equals(h2));
			h2.ModTime = h1.ModTime;
			Assert.IsTrue(h1.Equals(h2));

			h1.TypeFlag = 165;
			Assert.IsFalse(h1.Equals(h2));
			h2.TypeFlag = h1.TypeFlag;
			Assert.IsTrue(h1.Equals(h2));

			h1.LinkName = "link";
			Assert.IsFalse(h1.Equals(h2));
			h2.LinkName = h1.LinkName;
			Assert.IsTrue(h1.Equals(h2));
		
			h1.Magic = "ustar";
			Assert.IsFalse(h1.Equals(h2));
			h2.Magic = h1.Magic;
			Assert.IsTrue(h1.Equals(h2));
		
			h1.Version = "1";
			Assert.IsFalse(h1.Equals(h2));
			h2.Version = h1.Version;
			Assert.IsTrue(h1.Equals(h2));
		
			h1.UserName = "******";
			Assert.IsFalse(h1.Equals(h2));
			h2.UserName = h1.UserName;
			Assert.IsTrue(h1.Equals(h2));
		
			h1.GroupName = "group";
			Assert.IsFalse(h1.Equals(h2));
			h2.GroupName = h1.GroupName;
			Assert.IsTrue(h1.Equals(h2));
		
		
			h1.DevMajor = 165;
			Assert.IsFalse(h1.Equals(h2));
			h2.DevMajor = h1.DevMajor;
			Assert.IsTrue(h1.Equals(h2));
		
			h1.DevMinor = 164;
			Assert.IsFalse(h1.Equals(h2));
			h2.DevMinor = h1.DevMinor;
			Assert.IsTrue(h1.Equals(h2));
			
		}
Пример #43
0
        /// <summary>
        /// Convenience method that will modify an entry's name directly
        /// in place in an entry header buffer byte array.
        /// </summary>
        /// <param name="outbuf">
        /// The buffer containing the entry header to modify.
        /// </param>
        /// <param name="newName">
        /// The new name to place into the header buffer.
        /// </param>
        public void AdjustEntryName(byte[] outbuf, string newName)
        {
            var offset = 0;

            TarHeader.GetNameBytes(newName, outbuf, offset, TarHeader.NAMELEN);
        }
Пример #44
0
		/// <summary>
		/// Fill in a TarHeader given only the entry's name.
		/// </summary>
		/// <param name="header">
		/// The TarHeader to fill in.
		/// </param>
		/// <param name="name">
		/// The tar entry name.
		/// </param>
		static public void NameTarHeader(TarHeader header, string name)
		{
			if ( header == null ) {
				throw new ArgumentNullException("header");
			}

			if ( name == null ) {
				throw new ArgumentNullException("name");
			}

			bool isDir = name.EndsWith("/");
			
			header.Name = name;
			header.Mode = isDir ? 1003 : 33216;
			header.UserId   = 0;
			header.GroupId  = 0;
			header.Size     = 0;
			
			header.ModTime  = DateTime.UtcNow;
			
			header.TypeFlag = isDir ? TarHeader.LF_DIR : TarHeader.LF_NORMAL;
			
			header.LinkName  = String.Empty;
			header.UserName  = String.Empty;
			header.GroupName = String.Empty;
			
			header.DevMajor = 0;
			header.DevMinor = 0;
		}
Пример #45
0
        /// <summary>
        /// Fill in a TarHeader with information from a File.
        /// </summary>
        /// <param name="hdr">
        /// The TarHeader to fill in.
        /// </param>
        /// <param name="file">
        /// The file from which to get the header information.
        /// </param>
        public void GetFileTarHeader(TarHeader hdr, string file)
        {
            this.file = file;

            // bugfix from torhovl from #D forum:
            var name = file;

#if !COMPACT_FRAMEWORK
            // 23-Jan-2004 GnuTar allows device names in path where the name is not local to the current directory
            if (name.IndexOf(Environment.CurrentDirectory) == 0)
            {
                name = name.Substring(Environment.CurrentDirectory.Length);
            }
#endif

/*
 *                      if (Path.DirectorySeparatorChar == '\\')
 *                      {  // check if the OS is Windows
 *                              // Strip off drive letters!
 *                              if (name.Length > 2)
 *                              {
 *                                      char ch1 = name[0];
 *                                      char ch2 = name[1];
 *
 *                                      if (ch2 == ':' && Char.IsLetter(ch1))
 *                                      {
 *                                              name = name.Substring(2);
 *                                      }
 *                              }
 *                      }
 */

            name = name.Replace(Path.DirectorySeparatorChar, '/');

            // No absolute pathnames
            // Windows (and Posix?) paths can start with UNC style "\\NetworkDrive\",
            // so we loop on starting /'s.
            while (name.StartsWith("/"))
            {
                name = name.Substring(1);
            }

            hdr.LinkName = String.Empty;
            hdr.Name     = name;

            if (Directory.Exists(file))
            {
                hdr.Mode     = 1003;                 // Magic number for security access for a UNIX filesystem
                hdr.TypeFlag = TarHeader.LF_DIR;
                if (hdr.Name.Length == 0 || hdr.Name[hdr.Name.Length - 1] != '/')
                {
                    hdr.Name = hdr.Name + "/";
                }

                hdr.Size = 0;
            }
            else
            {
                hdr.Mode     = 33216;                 // Magic number for security access for a UNIX filesystem
                hdr.TypeFlag = TarHeader.LF_NORMAL;
                hdr.Size     = new FileInfo(file.Replace('/', Path.DirectorySeparatorChar)).Length;
            }

            hdr.ModTime  = System.IO.File.GetLastWriteTime(file.Replace('/', Path.DirectorySeparatorChar)).ToUniversalTime();
            hdr.DevMajor = 0;
            hdr.DevMinor = 0;
        }
Пример #46
0
		/// <summary>
		/// Construct an entry from an archive's header bytes. File is set
		/// to null.
		/// </summary>
		/// <param name = "headerBuffer">
		/// The header bytes from a tar archive entry.
		/// </param>
		public TarEntry(byte[] headerBuffer)
		{
			header = new TarHeader();
			header.ParseBuffer(headerBuffer);
		}
Пример #47
0
        /// <summary>
        /// Fill in a TarHeader with information from a File.
        /// </summary>
        /// <param name="header">
        /// The TarHeader to fill in.
        /// </param>
        /// <param name="file">
        /// The file from which to get the header information.
        /// </param>
        public void GetFileTarHeader(TarHeader header, string file)
        {
            if (header == null)
            {
                throw new ArgumentNullException("header");
            }

            if (file == null)
            {
                throw new ArgumentNullException("file");
            }

            this.file = file;

            // bugfix from torhovl from #D forum:
            string name = file;

            // 23-Jan-2004 GnuTar allows device names in path where the name is not local to the current directory
            if (name.IndexOf(Directory.GetCurrentDirectory(), StringComparison.Ordinal) == 0)
            {
                name = name.Substring(Directory.GetCurrentDirectory().Length);
            }

            /*
             *                      if (Path.DirectorySeparatorChar == '\\')
             *                      {
             *                              // check if the OS is Windows
             *                              // Strip off drive letters!
             *                              if (name.Length > 2)
             *                              {
             *                                      char ch1 = name[0];
             *                                      char ch2 = name[1];
             *
             *                                      if (ch2 == ':' && Char.IsLetter(ch1))
             *                                      {
             *                                              name = name.Substring(2);
             *                                      }
             *                              }
             *                      }
             */

            name = name.Replace(Path.DirectorySeparatorChar, '/');

            // No absolute pathnames
            // Windows (and Posix?) paths can start with UNC style "\\NetworkDrive\",
            // so we loop on starting /'s.
            while (name.StartsWith("/", StringComparison.Ordinal))
            {
                name = name.Substring(1);
            }

            header.LinkName = String.Empty;
            header.Name     = name;

            if (Directory.Exists(file))
            {
                header.Mode     = 1003;             // Magic number for security access for a UNIX filesystem
                header.TypeFlag = TarHeader.LF_DIR;
                if ((header.Name.Length == 0) || header.Name[header.Name.Length - 1] != '/')
                {
                    header.Name = header.Name + "/";
                }

                header.Size = 0;
            }
            else
            {
                header.Mode     = 33216;             // Magic number for security access for a UNIX filesystem
                header.TypeFlag = TarHeader.LF_NORMAL;
                header.Size     = new FileInfo(file.Replace('/', Path.DirectorySeparatorChar)).Length;
            }

            header.ModTime  = System.IO.File.GetLastWriteTime(file.Replace('/', Path.DirectorySeparatorChar)).ToUniversalTime();
            header.DevMajor = 0;
            header.DevMinor = 0;
        }