Skip to content

Commit

Permalink
[release/7.0-preview4] Backport new Tar APIs (#68337)
Browse files Browse the repository at this point in the history
* Implement Tar APIs (#67883)

API proposal: #65951

* Add assembly to NetCoreAppLibrary.props

* Remove <PackageDescription> from src csproj since it is not OOB.

* Add NetCoreAppCurrent to src csproj TargetFrameworks

* Additional src csproj changes.

* Allow sharing of input tar file for read

Co-authored-by: carlossanlop <[email protected]>
Co-authored-by: Dan Moseley <[email protected]>
  • Loading branch information
3 people authored Apr 22, 2022
1 parent eb9dd67 commit 083181f
Show file tree
Hide file tree
Showing 79 changed files with 9,936 additions and 42 deletions.
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

0 comments on commit 083181f

Please sign in to comment.