Esempio n. 1
0
        /// <param name="archive"></param><param name="extractDirectory"></param> <param name="wantExtract"></param>
        /// <returns></returns>
        private List<TarEntry> InternalListOrExtract(string archive, string extractDirectory, bool wantExtract)
        {
            var entryList = new List<TarEntry>();
            var block = new byte[512];
            int blocksToMunch = 0;
            int remainingBytes = 0;
            Stream output = null;
            DateTime mtime = DateTime.Now;
            string name = null;
            TarEntry entry = null;
            var deferredDirTimestamp = new Dictionary<string, DateTime>();

            if (!File.Exists(archive))
            {
                throw new FileNotFoundException("The archive does not exist", archive);
            }

            using (Stream fs = this.InternalGetInputStream(archive))
            {
                while (fs.Read(block, 0, block.Length) > 0)
                {
                    if (blocksToMunch > 0)
                    {
                        if (output != null)
                        {
                            int bytesToWrite = (block.Length < remainingBytes) ? block.Length : remainingBytes;

                            output.Write(block, 0, bytesToWrite);
                            remainingBytes -= bytesToWrite;
                        }

                        blocksToMunch--;

                        if (blocksToMunch == 0)
                        {
                            if (output != null)
                            {
                                if (output is MemoryStream)
                                {
                                    entry.Name =
                                        name = Encoding.ASCII.GetString((output as MemoryStream).ToArray()).TrimNull();
                                }

                                output.Close();
                                output.Dispose();

                                if (output is FileStream && !this.TarOptions.DoNotSetTime)
                                {
                                    File.SetLastWriteTimeUtc(Path.Combine(extractDirectory, name), mtime);
                                }

                                output = null;
                            }
                        }

                        continue;
                    }

                    HeaderBlock hb = this.Serializer.RawDeserialize(block);

                    if (!hb.VerifyChksum())
                    {
                        throw new Exception("header checksum is invalid.");
                    }

                    // if this is the first entry, or if the prior entry is not a GnuLongName
                    if (entry == null || entry.Type != TarEntryType.GnuLongName)
                    {
                        name = hb.GetName();
                    }

                    if (string.IsNullOrEmpty(name))
                    {
                        break; // EOF
                    }

                    mtime = hb.GetMtime();
                    remainingBytes = hb.GetSize();

                    if (hb.TypeFlag == 0)
                    {
                        hb.TypeFlag = (byte)'0'; // coerce old-style GNU type to posix tar type
                    }

                    entry = new TarEntry
                        {
                           Name = name, Mtime = mtime, Size = remainingBytes, @Type = (TarEntryType)hb.TypeFlag
                        };

                    if (entry.Type != TarEntryType.GnuLongName)
                    {
                        entryList.Add(entry);
                    }

                    blocksToMunch = (remainingBytes > 0) ? ((remainingBytes - 1) / 512) + 1 : 0;

                    if (entry.Type == TarEntryType.GnuLongName)
                    {
                        if (name != "././@LongLink")
                        {
                            if (wantExtract)
                            {
                                throw new Exception(
                                    string.Format(
                                        "unexpected name for type 'L' (expected '././@LongLink', got '{0}')", name));
                            }
                        }

                        // for GNU long names, we extract the long name info into a memory stream
                        output = new MemoryStream();
                        continue;
                    }

                    if (!wantExtract)
                    {
                    }
                    else
                    {
                        switch (entry.Type)
                        {
                            case TarEntryType.Directory:
                                if (!Directory.Exists(Path.Combine(extractDirectory, name)))
                                {
                                    Directory.CreateDirectory(Path.Combine(extractDirectory, name));

                                    // cannot set the time on the directory now, or it will be updated
                                    // by future file writes.  Defer until after all file writes are done.
                                    if (!this.TarOptions.DoNotSetTime)
                                    {
                                        deferredDirTimestamp.Add(
                                            Path.Combine(extractDirectory, name).TrimSlash(), mtime);
                                    }
                                }
                                else if (this.TarOptions.Overwrite)
                                {
                                    if (!this.TarOptions.DoNotSetTime)
                                    {
                                        deferredDirTimestamp.Add(
                                            Path.Combine(extractDirectory, name).TrimSlash(), mtime);
                                    }
                                }

                                break;

                            case TarEntryType.FileOld:
                            case TarEntryType.File:
                            case TarEntryType.FileContiguous:
                                string p = Path.GetDirectoryName(Path.Combine(extractDirectory, name));
                                if (!string.IsNullOrEmpty(p))
                                {
                                    if (!Directory.Exists(p))
                                    {
                                        Directory.CreateDirectory(p);
                                    }
                                }

                                output = this.InternalGetExtractOutputStream(name, extractDirectory);
                                break;

                            case TarEntryType.GnuVolumeHeader:
                            case TarEntryType.CharSpecial:
                            case TarEntryType.BlockSpecial:

                                // do nothing on extract
                                break;

                            case TarEntryType.SymbolicLink:
                                break;

                            default:
                                throw new Exception(string.Format("unsupported entry type ({0})", hb.TypeFlag));
                        }
                    }
                }
            }

            // apply the deferred timestamps on the directories
            if (deferredDirTimestamp.Count > 0)
            {
                foreach (string key in deferredDirTimestamp.Keys)
                {
                    Directory.SetLastWriteTimeUtc(key, deferredDirTimestamp[key]);
                }
            }

            return entryList;
        }
Esempio n. 2
0
        /// <param name="archive"></param><param name="extractDirectory"></param> <param name="wantExtract"></param>
        /// <returns></returns>
        private List <TarEntry> InternalListOrExtract(string archive, string extractDirectory, bool wantExtract)
        {
            var      entryList            = new List <TarEntry>();
            var      block                = new byte[512];
            int      blocksToMunch        = 0;
            int      remainingBytes       = 0;
            Stream   output               = null;
            DateTime mtime                = DateTime.Now;
            string   name                 = null;
            TarEntry entry                = null;
            var      deferredDirTimestamp = new Dictionary <string, DateTime>();

            if (!File.Exists(archive))
            {
                throw new FileNotFoundException("The archive does not exist", archive);
            }

            using (Stream fs = this.InternalGetInputStream(archive))
            {
                while (fs.Read(block, 0, block.Length) > 0)
                {
                    if (blocksToMunch > 0)
                    {
                        if (output != null)
                        {
                            int bytesToWrite = (block.Length < remainingBytes) ? block.Length : remainingBytes;

                            output.Write(block, 0, bytesToWrite);
                            remainingBytes -= bytesToWrite;
                        }

                        blocksToMunch--;

                        if (blocksToMunch == 0)
                        {
                            if (output != null)
                            {
                                if (output is MemoryStream)
                                {
                                    entry.Name =
                                        name   = Encoding.ASCII.GetString((output as MemoryStream).ToArray()).TrimNull();
                                }

                                output.Close();
                                output.Dispose();

                                if (output is FileStream && !this.TarOptions.DoNotSetTime)
                                {
                                    File.SetLastWriteTimeUtc(Path.Combine(extractDirectory, name), mtime);
                                }

                                output = null;
                            }
                        }

                        continue;
                    }

                    HeaderBlock hb = this.Serializer.RawDeserialize(block);

                    if (!hb.VerifyChksum())
                    {
                        throw new Exception("header checksum is invalid.");
                    }

                    // if this is the first entry, or if the prior entry is not a GnuLongName
                    if (entry == null || entry.Type != TarEntryType.GnuLongName)
                    {
                        name = hb.GetName();
                    }

                    if (string.IsNullOrEmpty(name))
                    {
                        break; // EOF
                    }

                    mtime          = hb.GetMtime();
                    remainingBytes = hb.GetSize();

                    if (hb.TypeFlag == 0)
                    {
                        hb.TypeFlag = (byte)'0'; // coerce old-style GNU type to posix tar type
                    }

                    entry = new TarEntry
                    {
                        Name = name, Mtime = mtime, Size = remainingBytes, @Type = (TarEntryType)hb.TypeFlag
                    };

                    if (entry.Type != TarEntryType.GnuLongName)
                    {
                        entryList.Add(entry);
                    }

                    blocksToMunch = (remainingBytes > 0) ? ((remainingBytes - 1) / 512) + 1 : 0;

                    if (entry.Type == TarEntryType.GnuLongName)
                    {
                        if (name != "././@LongLink")
                        {
                            if (wantExtract)
                            {
                                throw new Exception(
                                          string.Format(
                                              "unexpected name for type 'L' (expected '././@LongLink', got '{0}')", name));
                            }
                        }

                        // for GNU long names, we extract the long name info into a memory stream
                        output = new MemoryStream();
                        continue;
                    }

                    if (!wantExtract)
                    {
                    }
                    else
                    {
                        switch (entry.Type)
                        {
                        case TarEntryType.Directory:
                            if (!Directory.Exists(Path.Combine(extractDirectory, name)))
                            {
                                Directory.CreateDirectory(Path.Combine(extractDirectory, name));

                                // cannot set the time on the directory now, or it will be updated
                                // by future file writes.  Defer until after all file writes are done.
                                if (!this.TarOptions.DoNotSetTime)
                                {
                                    deferredDirTimestamp.Add(
                                        Path.Combine(extractDirectory, name).TrimSlash(), mtime);
                                }
                            }
                            else if (this.TarOptions.Overwrite)
                            {
                                if (!this.TarOptions.DoNotSetTime)
                                {
                                    deferredDirTimestamp.Add(
                                        Path.Combine(extractDirectory, name).TrimSlash(), mtime);
                                }
                            }

                            break;

                        case TarEntryType.FileOld:
                        case TarEntryType.File:
                        case TarEntryType.FileContiguous:
                            string p = Path.GetDirectoryName(Path.Combine(extractDirectory, name));
                            if (!string.IsNullOrEmpty(p))
                            {
                                if (!Directory.Exists(p))
                                {
                                    Directory.CreateDirectory(p);
                                }
                            }

                            output = this.InternalGetExtractOutputStream(name, extractDirectory);
                            break;

                        case TarEntryType.GnuVolumeHeader:
                        case TarEntryType.CharSpecial:
                        case TarEntryType.BlockSpecial:

                            // do nothing on extract
                            break;

                        case TarEntryType.SymbolicLink:
                            break;

                        default:
                            throw new Exception(string.Format("unsupported entry type ({0})", hb.TypeFlag));
                        }
                    }
                }
            }

            // apply the deferred timestamps on the directories
            if (deferredDirTimestamp.Count > 0)
            {
                foreach (string key in deferredDirTimestamp.Keys)
                {
                    Directory.SetLastWriteTimeUtc(key, deferredDirTimestamp[key]);
                }
            }

            return(entryList);
        }