Exemplo n.º 1
0
        public static void WriteEntry(Stream stream, ArchiveEntry entry, Stream data = null)
        {
            var targetPath = entry.TargetPath;

            if (!targetPath.StartsWith("."))
            {
                targetPath = "." + targetPath;
            }

            // Handle long file names (> 99 characters). If this is the case, add a "././@LongLink" pseudo-entry
            // which contains the full name.
            if (targetPath.Length > 99)
            {
                // Must include a trailing \0
                var    nameLength = Encoding.UTF8.GetByteCount(targetPath);
                byte[] entryName  = new byte[nameLength + 1];

                Encoding.UTF8.GetBytes(targetPath, 0, targetPath.Length, entryName, 0);

                ArchiveEntry nameEntry = new ArchiveEntry()
                {
                    Mode       = entry.Mode,
                    Modified   = entry.Modified,
                    TargetPath = "././@LongLink",
                    Owner      = entry.Owner,
                    Group      = entry.Group
                };

                using (MemoryStream nameStream = new MemoryStream(entryName))
                {
                    WriteEntry(stream, nameEntry, nameStream);
                }

                targetPath = targetPath.Substring(0, 99);
            }

            var isDir  = entry.Mode.HasFlag(LinuxFileMode.S_IFDIR);
            var isLink = !isDir && !string.IsNullOrWhiteSpace(entry.LinkTo);
            var isFile = !isDir && !isLink;

            TarTypeFlag type;

            if (entry.TargetPath == "././@LongLink")
            {
                type = TarTypeFlag.LongName;
            }
            else if (isFile)
            {
                type = TarTypeFlag.RegType;
            }
            else if (isDir)
            {
                type = TarTypeFlag.DirType;
            }
            else
            {
                type = TarTypeFlag.SymType;
            }

            bool dispose = false;

            if (data == null)
            {
                if (isFile)
                {
                    dispose = true;
                    data    = File.OpenRead(entry.SourceFilename);
                }
                else
                {
                    data = new MemoryStream();
                }
            }

            try
            {
                var hdr = new TarHeader()
                {
                    // No need to set the file type, the tar header has a special field for that.
                    FileMode     = entry.Mode & LinuxFileMode.PermissionsMask,
                    DevMajor     = null,
                    DevMinor     = null,
                    FileName     = targetPath,
                    FileSize     = (uint)data.Length,
                    GroupId      = 0,
                    UserId       = 0,
                    GroupName    = entry.Group,
                    LinkName     = isLink ? entry.LinkTo : string.Empty,
                    Prefix       = string.Empty,
                    TypeFlag     = type,
                    UserName     = entry.Owner,
                    Version      = null,
                    LastModified = entry.Modified,
                    Magic        = "ustar"
                };
                WriteEntry(stream, hdr, data);
            }
            finally
            {
                if (dispose)
                {
                    data.Dispose();
                }
            }
        }