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(); } } }