-
Notifications
You must be signed in to change notification settings - Fork 5k
Implement Tar APIs #67883
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
Implement Tar APIs #67883
Changes from all commits
e9fbcc9
0731cb2
8f1f1af
10df463
da4af67
8710ceb
76e484c
c9c4d85
e0dafda
5b8392b
a16d4d9
7ca674e
560b789
b3e5988
c22a8e7
d3e4f31
23caa17
e0b0442
b682576
9fd01c3
7b0d8c3
f1d9b7b
0980fbd
a28f3e5
7f2e516
3f71b60
cb855ed
dd40447
9a28f12
40097c6
b1e8dfc
c11e434
255ec96
8ae7788
d3cbdd2
6b5d078
19eb98d
69ca3e7
b1a2d5a
fb644dd
cd40d62
0ee2c33
58a3476
fc0e568
5d81577
a52dfe4
b227fa9
5745b9f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: make |
||
} | ||
} |
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 |
---|---|---|
@@ -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); | ||
} | ||
} |
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++) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. StringBuilder indexing is expensive, so the below has non-trivial expense. StringBuilder is also unnecessary here. And this ends up allocating a new string (and StringBuilder) even if nothing needs to be changed. This method should instead be more like: internal static string SanitizeEntryFilePath(string entryPath)
{
for (int i = 0; i < entryPath.Length; i++)
{
if (IsInvalid(entryPath[i]))
{
return string.Create(entryPath.Length, (entryPath, i), (dest, state) =>
{
string entryPath = state.entryPath;
entryPath.AsSpan(0, state.i).CopyTo(dest);
for (int i = state.i; (uint)i < (uint)entryPath.Length; i++)
{
dest[i] = IsInvalid(entryPath[i]) ? '_' : entryPath[i];
}
});
}
}
return entryPath;
static bool IsInvalid(char c)
{
switch (c)
{
case >= '\0' and < (char)32:
case '?' or ':' or '*' or '"' or '<' or '>' or '|':
return true;
default:
return false;
}
}
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (There should also be a comment about why these are invalid. Don't we typically leave such decisions up to the OS now?) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This code was originally merged in another PR. I merely renamed the class so it would make sense for usage in both zip and tar. Since it isn't really new code, I would like to address this suggestion in a future PR. |
||
{ | ||
if (((int)builder[i] >= 0 && (int)builder[i] < 32) || | ||
builder[i] == '?' || builder[i] == ':' || | ||
|
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 |
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) { } | ||
} | ||
} |
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> |
Uh oh!
There was an error while loading. Please reload this page.