Пример #1
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));
			
		}
Пример #2
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)
            {
                var longHeader = new TarHeader{TypeFlag = TarHeader.LF_GNU_LONGNAME};
                longHeader.Name = longHeader.Name + "././@LongLink";
                longHeader.UserId = 0;
                longHeader.GroupId = 0;
                longHeader.GroupName = String.Empty;
                longHeader.UserName = String.Empty;
                longHeader.LinkName = String.Empty;

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

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

                var nameCharIndex = 0;

                while (nameCharIndex < entry.TarHeader.Name.Length)
                {
                    Array.Clear(blockBuffer, 0, blockBuffer.Length);
                    TarHeader.GetAsciiBytes(entry.TarHeader.Name, nameCharIndex, blockBuffer, 0, TarBuffer.BlockSize);
                    nameCharIndex += TarBuffer.BlockSize;
                    _buffer.WriteBlock(blockBuffer);
                }
            }

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

            currBytes = 0;

            currSize = entry.IsDirectory ? 0 : entry.Size;
        }
Пример #3
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("header");
            }

            _header = (TarHeader) header.Clone();
        }
Пример #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 (hasHitEOF)
            {
                return null;
            }

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

            var headerBuf = _buffer.ReadBlock();

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

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

                    StringBuilder longName = null;

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

                        longName = new StringBuilder();

                        while (numToRead > 0)
                        {
                            var numRead = 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 = _buffer.ReadBlock();
                    }
                    else if (header.TypeFlag == TarHeader.LF_GHDR)
                    {
                        // POSIX global extended header 
                        // Ignore things we dont understand completely for now
                        SkipToNextEntry();
                        headerBuf = _buffer.ReadBlock();
                    }
                    else if (header.TypeFlag == TarHeader.LF_XHDR)
                    {
                        // POSIX extended header
                        // Ignore things we dont understand completely for now
                        SkipToNextEntry();
                        headerBuf = _buffer.ReadBlock();
                    }
                    else if (header.TypeFlag == TarHeader.LF_GNU_VOLHDR)
                    {
                        // TODO: could show volume name when verbose
                        SkipToNextEntry();
                        headerBuf = _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 = _buffer.ReadBlock();
                    }

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

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

                    entryOffset = 0;

                    // TODO: Review How do we resolve this discrepancy?!
                    entrySize = currentEntry.Size;
                }
                catch (InvalidHeaderException ex)
                {
                    entrySize = 0;
                    entryOffset = 0;
                    currentEntry = null;
                    var errorText = string.Format("Bad header in record {0} block {1} {2}",
                                                  _buffer.CurrentRecord, _buffer.CurrentBlock, ex.Message);
                    throw new InvalidHeaderException(errorText);
                }
            }
            return currentEntry;
        }
Пример #5
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);
 }
Пример #6
0
 /// <summary>
 /// Initialise a default instance of <see cref="TarEntry"/>.
 /// </summary>
 private TarEntry()
 {
     _header = new TarHeader();
 }
Пример #7
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>
        public static void NameTarHeader(TarHeader header, string name)
        {
            if (header == null)
            {
                throw new ArgumentNullException("header");
            }

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

            var 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;
        }
Пример #8
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");
            }

            _file = file;

            // bugfix from torhovl from #D forum:
            var 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) == 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("/"))
            {
                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;
        }
Пример #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 (hasHitEOF)
            {
                return(null);
            }

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

            var headerBuf = _buffer.ReadBlock();

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

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

                    StringBuilder longName = null;

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

                        longName = new StringBuilder();

                        while (numToRead > 0)
                        {
                            var numRead = 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 = _buffer.ReadBlock();
                    }
                    else if (header.TypeFlag == TarHeader.LF_GHDR)
                    {
                        // POSIX global extended header
                        // Ignore things we dont understand completely for now
                        SkipToNextEntry();
                        headerBuf = _buffer.ReadBlock();
                    }
                    else if (header.TypeFlag == TarHeader.LF_XHDR)
                    {
                        // POSIX extended header
                        // Ignore things we dont understand completely for now
                        SkipToNextEntry();
                        headerBuf = _buffer.ReadBlock();
                    }
                    else if (header.TypeFlag == TarHeader.LF_GNU_VOLHDR)
                    {
                        // TODO: could show volume name when verbose
                        SkipToNextEntry();
                        headerBuf = _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 = _buffer.ReadBlock();
                    }

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

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

                    entryOffset = 0;

                    // TODO: Review How do we resolve this discrepancy?!
                    entrySize = currentEntry.Size;
                }
                catch (InvalidHeaderException ex)
                {
                    entrySize    = 0;
                    entryOffset  = 0;
                    currentEntry = null;
                    var errorText = string.Format("Bad header in record {0} block {1} {2}",
                                                  _buffer.CurrentRecord, _buffer.CurrentBlock, ex.Message);
                    throw new InvalidHeaderException(errorText);
                }
            }
            return(currentEntry);
        }