Skip to content

[release/7.0-preview4] Backport new Tar APIs #68337

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Apr 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions eng/Version.Details.xml
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,10 @@
<Uri>https://github.com/dotnet/runtime-assets</Uri>
<Sha>78cb33dbb0fb5156f049b9e1778f47b508f1be9f</Sha>
</Dependency>
<Dependency Name="System.Formats.Tar.TestData" Version="7.0.0-beta.22214.1">
<Uri>https://github.com/dotnet/runtime-assets</Uri>
<Sha>78cb33dbb0fb5156f049b9e1778f47b508f1be9f</Sha>
</Dependency>
<Dependency Name="System.IO.Compression.TestData" Version="7.0.0-beta.22214.1">
<Uri>https://github.com/dotnet/runtime-assets</Uri>
<Sha>78cb33dbb0fb5156f049b9e1778f47b508f1be9f</Sha>
Expand Down
1 change: 1 addition & 0 deletions eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@
<SystemRuntimeNumericsTestDataVersion>7.0.0-beta.22214.1</SystemRuntimeNumericsTestDataVersion>
<SystemComponentModelTypeConverterTestDataVersion>7.0.0-beta.22214.1</SystemComponentModelTypeConverterTestDataVersion>
<SystemDrawingCommonTestDataVersion>7.0.0-beta.22214.1</SystemDrawingCommonTestDataVersion>
<SystemFormatsTarTestDataVersion>7.0.0-beta.22214.1</SystemFormatsTarTestDataVersion>
<SystemIOCompressionTestDataVersion>7.0.0-beta.22214.1</SystemIOCompressionTestDataVersion>
<SystemIOPackagingTestDataVersion>7.0.0-beta.22214.1</SystemIOPackagingTestDataVersion>
<SystemNetTestDataVersion>7.0.0-beta.22214.1</SystemNetTestDataVersion>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Runtime.InteropServices;

internal static partial class Interop
{
// mknod: https://man7.org/linux/man-pages/man2/mknod.2.html
// makedev, major and minor: https://man7.org/linux/man-pages/man3/makedev.3.html
internal static partial class Sys
{
internal static int CreateBlockDevice(string pathName, uint mode, uint major, uint minor)
{
return MkNod(pathName, mode | FileTypes.S_IFBLK, major, minor);
}

internal static int CreateCharacterDevice(string pathName, uint mode, uint major, uint minor)
{
return MkNod(pathName, mode | FileTypes.S_IFCHR, major, minor);
}

[LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_MkNod", StringMarshalling = StringMarshalling.Utf8, SetLastError = true)]
private static partial int MkNod(string pathName, uint mode, uint major, uint minor);

[LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetDeviceIdentifiers", SetLastError = true)]
internal static unsafe partial int GetDeviceIdentifiers(ulong dev, uint* majorNumber, uint* minorNumber);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Runtime.InteropServices;

internal static partial class Interop
{
// mkfifo: https://man7.org/linux/man-pages/man3/mkfifo.3.html
internal static partial class Sys
{
[LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_MkFifo", StringMarshalling = StringMarshalling.Utf8, SetLastError = true)]
internal static partial int MkFifo(string pathName, uint mode);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ internal static class FileTypes
internal const int S_IFIFO = 0x1000;
internal const int S_IFCHR = 0x2000;
internal const int S_IFDIR = 0x4000;
internal const int S_IFBLK = 0x6000;
internal const int S_IFREG = 0x8000;
internal const int S_IFLNK = 0xA000;
internal const int S_IFSOCK = 0xC000;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.IO;
using System.Runtime.InteropServices;

internal static partial class Interop
{
internal static partial class Kernel32
{
internal static void CreateHardLink(string hardLinkFilePath, string targetFilePath)
{
string originalPath = hardLinkFilePath;
hardLinkFilePath = PathInternal.EnsureExtendedPrefix(hardLinkFilePath);
targetFilePath = PathInternal.EnsureExtendedPrefix(targetFilePath);

if (!CreateHardLinkPrivate(hardLinkFilePath, targetFilePath, IntPtr.Zero))
{
throw Win32Marshal.GetExceptionForLastWin32Error(originalPath);
}
}

[LibraryImport(Libraries.Kernel32, EntryPoint = "CreateHardLinkW", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)]
[return: MarshalAs(UnmanagedType.Bool)]
private static partial bool CreateHardLinkPrivate(string lpFileName, string lpExistingFileName, IntPtr lpSecurityAttributes);
}
}
10 changes: 10 additions & 0 deletions src/libraries/Common/src/System/IO/Archiving.Utils.Unix.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace System.IO
{
internal static partial class ArchivingUtils
{
internal static string SanitizeEntryFilePath(string entryPath) => entryPath.Replace('\0', '_');
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
// Licensed to the .NET Foundation under one or more agreements.
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.


using System.Text;

namespace System.IO.Compression
namespace System.IO
{
public static partial class ZipFileExtensions
internal static partial class ArchivingUtils
{
internal static string SanitizeZipFilePath(string zipPath)
internal static string SanitizeEntryFilePath(string entryPath)
{
StringBuilder builder = new StringBuilder(zipPath);
for (int i = 0; i < zipPath.Length; i++)
StringBuilder builder = new StringBuilder(entryPath);
for (int i = 0; i < entryPath.Length; i++)
{
if (((int)builder[i] >= 0 && (int)builder[i] < 32) ||
builder[i] == '?' || builder[i] == ':' ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
using System.Collections.Generic;
using System.Diagnostics;

namespace System.IO.Compression
namespace System.IO
{
internal static partial class ZipFileUtils
internal static partial class ArchivingUtils
{
// Per the .ZIP File Format Specification 4.4.17.1 all slashes should be forward slashes
// To ensure tar files remain compatible with Unix,
// and per the ZIP File Format Specification 4.4.17.1,
// all slashes should be forward slashes.
private const char PathSeparatorChar = '/';
private const string PathSeparatorString = "/";

Expand Down Expand Up @@ -74,5 +76,17 @@ public static bool IsDirEmpty(DirectoryInfo possiblyEmptyDir)
using (IEnumerator<string> enumerator = Directory.EnumerateFileSystemEntries(possiblyEmptyDir.FullName).GetEnumerator())
return !enumerator.MoveNext();
}

public static void AttemptSetLastWriteTime(string destinationFileName, DateTimeOffset lastWriteTime)
{
try
{
File.SetLastWriteTime(destinationFileName, lastWriteTime.DateTime);
}
catch (UnauthorizedAccessException)
{
// Some OSes like Android (#35374) might not support setting the last write time, the extraction should not fail because of that
}
}
}
}
5 changes: 4 additions & 1 deletion src/libraries/Common/tests/Resources/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@
<data name="Argument_InvalidPathChars" xml:space="preserve">
<value>Argument_InvalidPathChars {0}</value>
</data>
<data name="ArgumentOutOfRange_FileLengthTooBig" xml:space="preserve">
<value>Specified file length was too large for the file system.</value>
</data>
<data name="IO_FileNotFound" xml:space="preserve">
<value>IO_FileNotFound</value>
</data>
Expand Down Expand Up @@ -201,4 +204,4 @@
<data name="net_quic_streamaborted" xml:space="preserve">
<value>Stream aborted by peer ({0}).</value>
</data>
</root>
</root>
1 change: 1 addition & 0 deletions src/libraries/NetCoreAppLibrary.props
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
System.Drawing.Primitives;
System.Dynamic.Runtime;
System.Formats.Asn1;
System.Formats.Tar;
System.Globalization;
System.Globalization.Calendars;
System.Globalization.Extensions;
Expand Down
48 changes: 48 additions & 0 deletions src/libraries/System.Formats.Tar/System.Formats.Tar.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.1.32119.435
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{9BE8AFF4-D37B-49AF-AFD3-A15E514AC8AE}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{55A8C7E4-925C-4F21-B68B-CEFC19137A4B}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{6CF0D830-3EE9-44B1-B548-EA8750AD7B3E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Formats.Tar", "ref\System.Formats.Tar.csproj", "{E0B882C6-2082-45F2-806E-568461A61975}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Formats.Tar", "src\System.Formats.Tar.csproj", "{9F751C2B-56DD-4604-A3F3-568627F8C006}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Formats.Tar.Tests", "tests\System.Formats.Tar.Tests.csproj", "{6FD1E284-7B50-4077-B73A-5B31CB0E3577}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E0B882C6-2082-45F2-806E-568461A61975}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E0B882C6-2082-45F2-806E-568461A61975}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E0B882C6-2082-45F2-806E-568461A61975}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E0B882C6-2082-45F2-806E-568461A61975}.Release|Any CPU.Build.0 = Release|Any CPU
{9F751C2B-56DD-4604-A3F3-568627F8C006}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9F751C2B-56DD-4604-A3F3-568627F8C006}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9F751C2B-56DD-4604-A3F3-568627F8C006}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9F751C2B-56DD-4604-A3F3-568627F8C006}.Release|Any CPU.Build.0 = Release|Any CPU
{6FD1E284-7B50-4077-B73A-5B31CB0E3577}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6FD1E284-7B50-4077-B73A-5B31CB0E3577}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6FD1E284-7B50-4077-B73A-5B31CB0E3577}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6FD1E284-7B50-4077-B73A-5B31CB0E3577}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{E0B882C6-2082-45F2-806E-568461A61975} = {9BE8AFF4-D37B-49AF-AFD3-A15E514AC8AE}
{9F751C2B-56DD-4604-A3F3-568627F8C006} = {55A8C7E4-925C-4F21-B68B-CEFC19137A4B}
{6FD1E284-7B50-4077-B73A-5B31CB0E3577} = {6CF0D830-3EE9-44B1-B548-EA8750AD7B3E}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {F9B8DA67-C83B-466D-907C-9541CDBDCFEF}
EndGlobalSection
EndGlobal
123 changes: 123 additions & 0 deletions src/libraries/System.Formats.Tar/ref/System.Formats.Tar.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// ------------------------------------------------------------------------------
// Changes to this file must follow the https://aka.ms/api-review process.
// ------------------------------------------------------------------------------

namespace System.Formats.Tar
{
public sealed partial class GnuTarEntry : System.Formats.Tar.PosixTarEntry
{
public GnuTarEntry(System.Formats.Tar.TarEntryType entryType, string entryName) { }
public System.DateTimeOffset AccessTime { get { throw null; } set { } }
public System.DateTimeOffset ChangeTime { get { throw null; } set { } }
}
public sealed partial class PaxTarEntry : System.Formats.Tar.PosixTarEntry
{
public PaxTarEntry(System.Formats.Tar.TarEntryType entryType, string entryName) { }
public PaxTarEntry(System.Formats.Tar.TarEntryType entryType, string entryName, System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, string>> extendedAttributes) { }
public System.Collections.Generic.IReadOnlyDictionary<string, string> ExtendedAttributes { get { throw null; } }
}
public abstract partial class PosixTarEntry : System.Formats.Tar.TarEntry
{
internal PosixTarEntry() { }
public int DeviceMajor { get { throw null; } set { } }
public int DeviceMinor { get { throw null; } set { } }
public string GroupName { get { throw null; } set { } }
public string UserName { get { throw null; } set { } }
}
public abstract partial class TarEntry
{
internal TarEntry() { }
public int Checksum { get { throw null; } }
public System.IO.Stream? DataStream { get { throw null; } set { } }
public System.Formats.Tar.TarEntryType EntryType { get { throw null; } }
public int Gid { get { throw null; } set { } }
public long Length { get { throw null; } }
public string LinkName { get { throw null; } set { } }
public System.Formats.Tar.TarFileMode Mode { get { throw null; } set { } }
public System.DateTimeOffset ModificationTime { get { throw null; } set { } }
public string Name { get { throw null; } set { } }
public int Uid { get { throw null; } set { } }
public void ExtractToFile(string destinationFileName, bool overwrite) { }
public override string ToString() { throw null; }
}
public enum TarEntryType : byte
{
V7RegularFile = (byte)0,
RegularFile = (byte)48,
HardLink = (byte)49,
SymbolicLink = (byte)50,
CharacterDevice = (byte)51,
BlockDevice = (byte)52,
Directory = (byte)53,
Fifo = (byte)54,
ContiguousFile = (byte)55,
DirectoryList = (byte)68,
LongLink = (byte)75,
LongPath = (byte)76,
MultiVolume = (byte)77,
RenamedOrSymlinked = (byte)78,
SparseFile = (byte)83,
TapeVolume = (byte)86,
GlobalExtendedAttributes = (byte)103,
ExtendedAttributes = (byte)120,
}
public static partial class TarFile
{
public static void CreateFromDirectory(string sourceDirectoryName, System.IO.Stream destination, bool includeBaseDirectory) { }
public static void CreateFromDirectory(string sourceDirectoryName, string destinationFileName, bool includeBaseDirectory) { }
public static void ExtractToDirectory(System.IO.Stream source, string destinationDirectoryName, bool overwriteFiles) { }
public static void ExtractToDirectory(string sourceFileName, string destinationDirectoryName, bool overwriteFiles) { }
}
[System.FlagsAttribute]
public enum TarFileMode
{
None = 0,
OtherExecute = 1,
OtherWrite = 2,
OtherRead = 4,
GroupExecute = 8,
GroupWrite = 16,
GroupRead = 32,
UserExecute = 64,
UserWrite = 128,
UserRead = 256,
StickyBit = 512,
GroupSpecial = 1024,
UserSpecial = 2048,
}
public enum TarFormat
{
Unknown = 0,
V7 = 1,
Ustar = 2,
Pax = 3,
Gnu = 4,
}
public sealed partial class TarReader : System.IDisposable
{
public TarReader(System.IO.Stream archiveStream, bool leaveOpen = false) { }
public System.Formats.Tar.TarFormat Format { get { throw null; } }
public System.Collections.Generic.IReadOnlyDictionary<string, string>? GlobalExtendedAttributes { get { throw null; } }
public void Dispose() { }
public System.Formats.Tar.TarEntry? GetNextEntry(bool copyData = false) { throw null; }
}
public sealed partial class TarWriter : System.IDisposable
{
public TarWriter(System.IO.Stream archiveStream, System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, string>>? globalExtendedAttributes = null, bool leaveOpen = false) { }
public TarWriter(System.IO.Stream archiveStream, System.Formats.Tar.TarFormat archiveFormat, bool leaveOpen = false) { }
public System.Formats.Tar.TarFormat Format { get { throw null; } }
public void Dispose() { }
public void WriteEntry(System.Formats.Tar.TarEntry entry) { }
public void WriteEntry(string fileName, string? entryName) { }
}
public sealed partial class UstarTarEntry : System.Formats.Tar.PosixTarEntry
{
public UstarTarEntry(System.Formats.Tar.TarEntryType entryType, string entryName) { }
}
public sealed partial class V7TarEntry : System.Formats.Tar.TarEntry
{
public V7TarEntry(System.Formats.Tar.TarEntryType entryType, string entryName) { }
}
}
13 changes: 13 additions & 0 deletions src/libraries/System.Formats.Tar/ref/System.Formats.Tar.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>$(NetCoreAppCurrent)</TargetFrameworks>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Compile Include="System.Formats.Tar.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\System.Runtime\ref\System.Runtime.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)System.Collections\ref\System.Collections.csproj" />
</ItemGroup>
</Project>
Loading