Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,6 @@ private void ExtractAsFifo(string destinationFileName)
Interop.CheckIo(Interop.Sys.MkFifo(destinationFileName, (uint)Mode), destinationFileName);
}

// Unix specific implementation of the method that extracts the current entry as a hard link.
private void ExtractAsHardLink(string targetFilePath, string hardLinkFilePath)
{
Debug.Assert(EntryType is TarEntryType.HardLink);
Debug.Assert(!string.IsNullOrEmpty(targetFilePath));
Debug.Assert(!string.IsNullOrEmpty(hardLinkFilePath));
File.CreateHardLink(hardLinkFilePath, targetFilePath);
}

// On Unix-like systems no explicit step is needed to make a file sparse: the kernel
// creates a hole whenever a write is preceded by a seek past the previous end. Most
// modern file systems (ext4, btrfs, xfs, APFS, ...) support sparse files; on those that
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,6 @@ private void ExtractAsFifo(string destinationFileName)
throw new InvalidOperationException(SR.IO_FifoFiles_NotSupported);
}

// Windows specific implementation of the method that extracts the current entry as a hard link.
private void ExtractAsHardLink(string targetFilePath, string hardLinkFilePath)
{
Debug.Assert(EntryType is TarEntryType.HardLink);
Debug.Assert(!string.IsNullOrEmpty(targetFilePath));
Debug.Assert(!string.IsNullOrEmpty(hardLinkFilePath));
File.CreateHardLink(hardLinkFilePath, targetFilePath);
}

// Best-effort attempt to mark the file as sparse on Windows so subsequent unwritten ranges
// remain real holes (unallocated extents) rather than being zero-filled on disk. The call
// is silently ignored if the underlying file system does not support sparse files
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,16 @@ private static void VerifyDestinationPath(string filePath, bool overwrite)
File.Delete(filePath);
}

// Extracts the current entry as a hard link. Shared between Unix and Windows since
// File.CreateHardLink is itself cross-platform.
private void ExtractAsHardLink(string targetFilePath, string hardLinkFilePath)
{
Debug.Assert(EntryType is TarEntryType.HardLink);
Debug.Assert(!string.IsNullOrEmpty(targetFilePath));
Debug.Assert(!string.IsNullOrEmpty(hardLinkFilePath));
File.CreateHardLink(hardLinkFilePath, targetFilePath);
}

// Extracts the current entry as a regular file into the specified destination.
// The assumption is that at this point there is no preexisting file or directory in that destination.
private void ExtractAsRegularFile(string destinationFileName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,22 +180,13 @@ internal static bool TryGetStringAsBaseTenLong(IReadOnlyDictionary<string, strin
// When writing an entry that came from an archive of a different format, if its entry type happens to
// be an incompatible regular file entry type, convert it to the compatible one.
// No change for all other entry types.
internal static TarEntryType GetCorrectTypeFlagForFormat(TarEntryFormat format, TarEntryType entryType)
{
if (format is TarEntryFormat.V7)
{
if (entryType is TarEntryType.RegularFile)
{
return TarEntryType.V7RegularFile;
}
}
else if (entryType is TarEntryType.V7RegularFile)
internal static TarEntryType GetCorrectTypeFlagForFormat(TarEntryFormat format, TarEntryType entryType) =>
(format, entryType) switch
{
return TarEntryType.RegularFile;
}

return entryType;
}
(TarEntryFormat.V7, TarEntryType.RegularFile) => TarEntryType.V7RegularFile,
(not TarEntryFormat.V7, TarEntryType.V7RegularFile) => TarEntryType.RegularFile,
_ => entryType,
};

/// <summary>Parses a numeric field.</summary>
internal static T ParseNumeric<T>(ReadOnlySpan<byte> buffer) where T : struct, INumber<T>, IBinaryInteger<T>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,7 @@ private TarEntry ConstructEntryForWriting(string fullPath, string entryName, Fil

FileSystemInfo info = entryType is TarEntryType.Directory ? new DirectoryInfo(fullPath) : new FileInfo(fullPath);

TarEntry entry = Format switch
{
TarEntryFormat.V7 => new V7TarEntry(entryType, entryName),
TarEntryFormat.Ustar => new UstarTarEntry(entryType, entryName),
TarEntryFormat.Pax => new PaxTarEntry(entryType, entryName),
TarEntryFormat.Gnu => new GnuTarEntry(entryType, entryName),
_ => throw new InvalidDataException(SR.Format(SR.TarInvalidFormat, Format)),
};
TarEntry entry = CreateEntryForFormat(entryType, entryName);

if (entryType is TarEntryType.BlockDevice or TarEntryType.CharacterDevice)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,7 @@ private TarEntry ConstructEntryForWriting(string fullPath, string entryName, Fil
throw new IOException(SR.Format(SR.TarUnsupportedFile, fullPath));
}

TarEntry entry = Format switch
{
TarEntryFormat.V7 => new V7TarEntry(entryType, entryName),
TarEntryFormat.Ustar => new UstarTarEntry(entryType, entryName),
TarEntryFormat.Pax => new PaxTarEntry(entryType, entryName),
TarEntryFormat.Gnu => new GnuTarEntry(entryType, entryName),
_ => throw new InvalidDataException(SR.Format(SR.TarInvalidFormat, Format)),
};
TarEntry entry = CreateEntryForFormat(entryType, entryName);

entry._header._mTime = fileInfo.ftLastWriteTime.ToDateTimeUtc();
// We do not set atime and ctime by default because many external tools are unable to read GNU entries
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -379,5 +379,16 @@ private static void ValidateEntryLinkName(TarEntryType entryType, string? linkNa
}
}
}

// Creates a new, empty entry of the type appropriate for the current archive Format.
private TarEntry CreateEntryForFormat(TarEntryType entryType, string entryName) =>
Format switch
{
TarEntryFormat.V7 => new V7TarEntry(entryType, entryName),
TarEntryFormat.Ustar => new UstarTarEntry(entryType, entryName),
TarEntryFormat.Pax => new PaxTarEntry(entryType, entryName),
TarEntryFormat.Gnu => new GnuTarEntry(entryType, entryName),
_ => throw new InvalidDataException(SR.Format(SR.TarInvalidFormat, Format)),
};
}
}
Loading