Example #1
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;
		}
Example #2
0
		/// <summary>
		/// Initialization code common to all pseudo constructors.
		/// </summary>
		void Initialize()
		{
			this.file   = null;
			this.header = new TarHeader();
		}
Example #3
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;

#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;
		}
Example #4
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) {
				this.hasHitEOF = true;
			} else if (this.buffer.IsEOFBlock(headerBuf)) {
				this.hasHitEOF = true;
			}
			
			if (this.hasHitEOF) {
				this.currEntry = 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.eFactory == null) {
						this.currEntry = new TarEntry(headerBuf);
						if (longName != null) {
							currEntry.Name = longName.ToString();
						}
					} else {
						this.currEntry = this.eFactory.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.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;
		}
Example #5
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;
		}
Example #6
0
 /// <summary>
 /// Add the checksum integer to header buffer.
 /// </summary>
 /// <param name = "val"></param>
 /// <param name = "buf">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>
 private static int GetCheckSumOctalBytes(long val, byte[] buf, int offset, int length)
 {
     TarHeader.GetOctalBytes(val, buf, offset, length - 1);
     return(offset + length);
 }
Example #7
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 = longHeader.Name + "././@LongLink";
				longHeader.UserId = 0;
				longHeader.GroupId = 0;
				longHeader.GroupName = "";
				longHeader.UserName = "";
				longHeader.LinkName = "";

				longHeader.Size = entry.TarHeader.Name.Length;

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

				int nameCharIndex = 0;

				while (nameCharIndex < entry.TarHeader.Name.Length) {
					Array.Clear(blockBuf, 0, blockBuf.Length);
					TarHeader.GetAsciiBytes(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 : entry.Size;
		}
Example #8
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;

#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;
        }
Example #9
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;

            TarHeader.GetNameBytes(newName, outbuf, offset, TarHeader.NAMELEN);
        }
Example #10
0
 /// <summary>
 /// Initialization code common to all pseudo constructors.
 /// </summary>
 void Initialize()
 {
     this.file   = null;
     this.header = new TarHeader();
 }
Example #11
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;
 }
Example #12
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;
		}