Ejemplo n.º 1
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 = tarBuffer.ReadBlock();

            if (headerBuf == null)
            {
                hasHitEOF = true;
            }
            else if (TarBuffer.IsEndOfArchiveBlock(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));
                            numToRead -= numRead;
                        }

                        SkipToNextEntry();
                        headerBuf = tarBuffer.ReadBlock();
                    }
                    else if (header.TypeFlag == TarHeader.LF_GHDR)                          // POSIX global extended header
                    // Ignore things we dont understand completely for now
                    {
                        SkipToNextEntry();
                        headerBuf = tarBuffer.ReadBlock();
                    }
                    else if (header.TypeFlag == TarHeader.LF_XHDR)                          // POSIX extended header
                    // Ignore things we dont understand completely for now
                    {
                        SkipToNextEntry();
                        headerBuf = tarBuffer.ReadBlock();
                    }
                    else if (header.TypeFlag == TarHeader.LF_GNU_VOLHDR)
                    {
                        // TODO: could show volume name when verbose
                        SkipToNextEntry();
                        headerBuf = tarBuffer.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 = tarBuffer.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}",
                                                  tarBuffer.CurrentRecord, tarBuffer.CurrentBlock, ex.Message);
                    throw new InvalidHeaderException(errorText);
                }
            }
            return(currentEntry);
        }
Ejemplo n.º 2
0
		/// <summary>
		/// Construct TarBuffer for writing Tar output to streams.
		/// </summary>
		/// <param name="outputStream">Output stream to write to.</param>
		/// <param name="blockFactor">Blocking factor to apply</param>
		/// <returns>A new <see cref="TarBuffer"/> suitable for output.</returns>
		public static TarBuffer CreateOutputTarBuffer(Stream outputStream, int blockFactor)
		{
			if ( outputStream == null )
			{
				throw new ArgumentNullException("outputStream");
			}

			if ( blockFactor <= 0 )
			{
#if NETCF_1_0
				throw new ArgumentOutOfRangeException("blockFactor");
#else
				throw new ArgumentOutOfRangeException("blockFactor", "Factor cannot be negative");
#endif				
			}

			var tarBuffer = new TarBuffer();
			tarBuffer.inputStream  = null;
			tarBuffer.outputStream = outputStream;
			tarBuffer.Initialize(blockFactor);
			
			return tarBuffer;
		}
Ejemplo n.º 3
0
 /// <summary>
 /// Construct a TarInputStream with user specified block factor
 /// </summary>
 /// <param name="inputStream">stream to source data from</param>
 /// <param name="blockFactor">block factor to apply to archive</param>
 public TarInputStream(Stream inputStream, int blockFactor)
 {
     this.inputStream = inputStream;
     tarBuffer        = TarBuffer.CreateInputTarBuffer(inputStream, blockFactor);
 }