Example #1
0
        /// <summary>
        /// Extract an entry from the archive. This method assumes that the
        /// tarIn stream has been properly set with a call to GetNextEntry().
        /// </summary>
        /// <param name="destDir">
        /// The destination directory into which to extract.
        /// </param>
        /// <param name="entry">
        /// The TarEntry returned by tarIn.GetNextEntry().
        /// </param>
        void ExtractEntry(string destDir, TarEntry entry)
        {
            OnProgressMessageEvent(entry, null);

            string name = entry.Name;

            if (Path.IsPathRooted(name))
            {
                // NOTE:
                // for UNC names...  \\machine\share\zoom\beet.txt gives \zoom\beet.txt
                name = name.Substring(Path.GetPathRoot(name).Length);
            }

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

            var regx = new Regex(@"[*|:<>?""]");

            //var matchs = regx.Matches(name);
            //foreach (Match match in matchs)
            //{
            //	var cha = match.Value.ToCharArray()[0];
            //	name = name.Replace(match.Value, $"[{(int)cha:X4}]");
            //}
            name = regx.Replace(name, "_");

            string destFile = Path.Combine(destDir, name);

            if (entry.IsDirectory)
            {
                EnsureDirectoryExists(destFile);
            }
            else
            {
                string parentDirectory = Path.GetDirectoryName(destFile);
                EnsureDirectoryExists(parentDirectory);

                bool process  = true;
                var  fileInfo = new FileInfo(destFile);
                if (fileInfo.Exists)
                {
                    if (keepOldFiles)
                    {
                        OnProgressMessageEvent(entry, "Destination file already exists");
                        process = false;
                    }
                    else if ((fileInfo.Attributes & FileAttributes.ReadOnly) != 0)
                    {
                        OnProgressMessageEvent(entry, "Destination file already exists, and is read-only");
                        process = false;
                    }
                }

                if (process)
                {
                    try
                    {
                        bool asciiTrans = false;

                        Stream outputStream = File.Create(destFile);
                        if (this.asciiTranslate)
                        {
                            asciiTrans = !IsBinary(destFile);
                        }

                        StreamWriter outw = null;
                        if (asciiTrans)
                        {
                            outw = new StreamWriter(outputStream);
                        }

                        byte[] rdbuf = new byte[32 * 1024];

                        while (true)
                        {
                            int numRead = tarIn.Read(rdbuf, 0, rdbuf.Length);

                            if (numRead <= 0)
                            {
                                break;
                            }

                            if (asciiTrans)
                            {
                                for (int off = 0, b = 0; b < numRead; ++b)
                                {
                                    if (rdbuf[b] == 10)
                                    {
                                        string s = Encoding.ASCII.GetString(rdbuf, off, (b - off));
                                        outw.WriteLine(s);
                                        off = b + 1;
                                    }
                                }
                            }
                            else
                            {
                                outputStream.Write(rdbuf, 0, numRead);
                            }
                        }

                        if (asciiTrans)
                        {
                            outw.Dispose();
                        }
                        else
                        {
                            outputStream.Dispose();
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e);
                    }
                }
            }
        }
Example #2
0
 /// <summary>
 /// Create a <see cref="TarEntry"/> based on named
 /// </summary>
 /// <param name="name">The name to use for the entry</param>
 /// <returns>A new <see cref="TarEntry"/></returns>
 public TarEntry CreateEntry(string name)
 {
     return(TarEntry.CreateTarEntry(name));
 }
Example #3
0
 /// <summary>
 /// Create a tar entry with details obtained from <paramref name="fileName">file</paramref>
 /// </summary>
 /// <param name="fileName">The name of the file to retrieve details from.</param>
 /// <returns>A new <see cref="TarEntry"/></returns>
 public TarEntry CreateEntryFromFile(string fileName)
 {
     return(TarEntry.CreateEntryFromFile(fileName));
 }
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 (hasHitEOF)
            {
                return(null);
            }

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

            byte[] headerBuf = tarBuffer.ReadBlock();

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

            if (hasHitEOF)
            {
                currentEntry = null;
            }
            else
            {
                try
                {
                    var header = new TarHeader();
                    header.ParseBuffer(headerBuf);
                    if (!header.IsChecksumValid)
                    {
                        throw TarException.InvalidHeader("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 TarException.UnKnown("Failed to read long name entry");
                            }

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

                        SkipToNextEntry();
                        headerBuf = this.tarBuffer.ReadBlock();
                    }
                    else if (header.TypeFlag == TarHeader.LF_GHDR)
                    {                      // POSIX global extended header
                        // Ignore things we dont understand completely for now
                        SkipToNextEntry();
                        headerBuf = this.tarBuffer.ReadBlock();
                    }
                    else if (header.TypeFlag == TarHeader.LF_XHDR)
                    {                      // POSIX extended header
                        // Ignore things we dont understand completely for now
                        SkipToNextEntry();
                        headerBuf = this.tarBuffer.ReadBlock();
                    }
                    else if (header.TypeFlag == TarHeader.LF_GNU_VOLHDR)
                    {
                        // TODO: could show volume name when verbose
                        SkipToNextEntry();
                        headerBuf = this.tarBuffer.ReadBlock();
                    }
                    else if (header.TypeFlag != TarHeader.LF_NORMAL &&
                             header.TypeFlag != TarHeader.LF_OLDNORM &&
                             header.TypeFlag != TarHeader.LF_LINK &&
                             header.TypeFlag != TarHeader.LF_SYMLINK &&
                             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 = this.currentEntry.Size;
                }
                catch (TarException ex)
                {
                    entrySize    = 0;
                    entryOffset  = 0;
                    currentEntry = null;
                    string errorText = string.Format("Bad header in record {0} block {1} {2}",
                                                     tarBuffer.CurrentRecord, tarBuffer.CurrentBlock, ex.Message);
                    throw TarException.UnKnown(errorText);
                }
            }
            return(currentEntry);
        }