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