// Copyright Epic Games, Inc. All Rights Reserved. using System; using System.IO.Compression; using System.Reflection; using System.Runtime.InteropServices; namespace EpicGames.Core { /// /// Additional functionality around to support non-Windows filesystems /// public static class ZipArchiveExtensions { /// /// Create a zip archive entry, preserving platform mode bits /// /// /// /// /// /// public static ZipArchiveEntry CreateEntryFromFile_CrossPlatform(this ZipArchive destination, string sourceFileName, string entryName, CompressionLevel compressionLevel) { ZipArchiveEntry entry = ZipFileExtensions.CreateEntryFromFile(destination, sourceFileName, entryName, compressionLevel); int result = -1; if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { result = FileUtils.GetFileMode_Linux(sourceFileName); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { result = FileUtils.GetFileMode_Mac(sourceFileName); } if(result >= 0) { entry.ExternalAttributes = (int)result << 16; } return entry; } /// /// Internal field storing information about the platform that created a ZipArchiveEntry. Cannot interpret how to treat the attribute bits without reading this. /// static readonly FieldInfo s_versionMadeByPlatformField = typeof(ZipArchiveEntry).GetField("_versionMadeByPlatform", BindingFlags.NonPublic | BindingFlags.Instance)!; /// /// Extract a zip archive entry, preserving platform mode bits /// /// /// /// public static void ExtractToFile_CrossPlatform(this ZipArchiveEntry entry, string targetFileName, bool overwrite) { ZipFileExtensions.ExtractToFile(entry, targetFileName, overwrite); if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { int madeByPlatform = Convert.ToInt32(s_versionMadeByPlatformField.GetValue(entry)!); if (madeByPlatform == 3 || madeByPlatform == 19) // Unix or OSX { FileUtils.SetFileMode_Linux(targetFileName, (ushort)(entry.ExternalAttributes >> 16)); } } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { int madeByPlatform = Convert.ToInt32(s_versionMadeByPlatformField.GetValue(entry)!); if (madeByPlatform == 3 || madeByPlatform == 19) // Unix or OSX { FileUtils.SetFileMode_Mac(targetFileName, (ushort)(entry.ExternalAttributes >> 16)); } } } } }