Skip to content

Commit

Permalink
Tar: for directories, use a default mask that has the 'x' bit. (#71760)
Browse files Browse the repository at this point in the history
* Tar: for directories, use a default mask that has the 'x' bit.

Without the 'x'-bit, the directories that get created are not
accessible.

* Apply suggestions from code review

Co-authored-by: Stephen Toub <stoub@microsoft.com>

* Update src/libraries/System.Formats.Tar/tests/TarTestsBase.cs

Co-authored-by: Stephen Toub <stoub@microsoft.com>

Co-authored-by: Stephen Toub <stoub@microsoft.com>
  • Loading branch information
tmds and stephentoub authored Jul 8, 2022
1 parent 53eb45d commit 502507a
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ internal TarEntry(TarEntryType entryType, string entryName, TarEntryFormat forma

// Default values for fields shared by all supported formats
_header._name = entryName;
_header._mode = (int)TarHelpers.DefaultMode;
_header._mode = TarHelpers.GetDefaultMode(entryType);
_header._mTime = DateTimeOffset.UtcNow;
_header._typeFlag = entryType;
_header._linkName = string.Empty;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ private static TarHeader GetDefaultGnuLongMetadataHeader(int longTextLength, Tar
TarHeader longMetadataHeader = default;

longMetadataHeader._name = GnuLongMetadataName; // Same name for both longpath or longlink
longMetadataHeader._mode = (int)TarHelpers.DefaultMode;
longMetadataHeader._mode = TarHelpers.GetDefaultMode(entryType);
longMetadataHeader._uid = 0;
longMetadataHeader._gid = 0;
longMetadataHeader._mTime = DateTimeOffset.MinValue; // 0
Expand Down Expand Up @@ -317,7 +317,7 @@ private void WriteAsPaxExtendedAttributes(Stream archiveStream, Span<byte> buffe
// The ustar fields (uid, gid, linkName, uname, gname, devmajor, devminor) do not get written.
// The mode gets the default value.
_name = GenerateExtendedAttributeName();
_mode = (int)TarHelpers.DefaultMode;
_mode = TarHelpers.GetDefaultMode(_typeFlag);
_typeFlag = isGea ? TarEntryType.GlobalExtendedAttributes : TarEntryType.ExtendedAttributes;
_linkName = string.Empty;
_magic = string.Empty;
Expand All @@ -338,7 +338,7 @@ private async Task<int> WriteAsPaxExtendedAttributesAsync(Stream archiveStream,
// The ustar fields (uid, gid, linkName, uname, gname, devmajor, devminor) do not get written.
// The mode gets the default value.
_name = GenerateExtendedAttributeName();
_mode = (int)TarHelpers.DefaultMode;
_mode = TarHelpers.GetDefaultMode(_typeFlag);
_typeFlag = isGea ? TarEntryType.GlobalExtendedAttributes : TarEntryType.ExtendedAttributes;
_linkName = string.Empty;
_magic = string.Empty;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,17 @@ internal static class TarHelpers
internal const byte EqualsChar = 0x3d;
internal const byte NewLineChar = 0xa;

internal const UnixFileMode DefaultMode = // 644 in octal
UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.GroupRead | UnixFileMode.OtherRead;
private const UnixFileMode DefaultFileMode =
UnixFileMode.UserRead | UnixFileMode.UserWrite |
UnixFileMode.GroupRead |
UnixFileMode.OtherRead;

private const UnixFileMode DefaultDirectoryMode =
DefaultFileMode |
UnixFileMode.UserExecute | UnixFileMode.GroupExecute | UnixFileMode.OtherExecute;

internal static int GetDefaultMode(TarEntryType type)
=> type is TarEntryType.Directory or TarEntryType.DirectoryList ? (int)DefaultDirectoryMode : (int)DefaultFileMode;

// Helps advance the stream a total number of bytes larger than int.MaxValue.
internal static void AdvanceStream(Stream archiveStream, long bytesToDiscard)
Expand Down
9 changes: 5 additions & 4 deletions src/libraries/System.Formats.Tar/tests/TarTestsBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ public abstract partial class TarTestsBase : FileCleanupTestBase
protected readonly string ModifiedEntryName = "ModifiedEntryName.ext";

// Default values are what a TarEntry created with its constructor will set
protected const UnixFileMode DefaultMode = UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.GroupRead | UnixFileMode.OtherRead; // 644 in octal, internally used as default
protected const UnixFileMode DefaultFileMode = UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.GroupRead | UnixFileMode.OtherRead; // 644 in octal, internally used as default
private const UnixFileMode DefaultDirectoryMode = DefaultFileMode | UnixFileMode.UserExecute | UnixFileMode.GroupExecute | UnixFileMode.OtherExecute; // 755 in octal, internally used as default
protected const UnixFileMode DefaultWindowsMode = UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute | UnixFileMode.GroupRead | UnixFileMode.GroupWrite | UnixFileMode.GroupExecute | UnixFileMode.OtherRead | UnixFileMode.OtherWrite | UnixFileMode.UserExecute; // Creating archives in Windows always sets the mode to 777
protected const int DefaultGid = 0;
protected const int DefaultUid = 0;
Expand Down Expand Up @@ -152,7 +153,7 @@ protected void SetCommonDirectory(TarEntry directory)
{
Assert.NotNull(directory);
Assert.Equal(TarEntryType.Directory, directory.EntryType);
SetCommonProperties(directory);
SetCommonProperties(directory, isDirectory: true);
}

protected void SetCommonHardLink(TarEntry hardLink)
Expand All @@ -177,7 +178,7 @@ protected void SetCommonSymbolicLink(TarEntry symbolicLink)
symbolicLink.LinkName = TestLinkName;
}

protected void SetCommonProperties(TarEntry entry)
protected void SetCommonProperties(TarEntry entry, bool isDirectory = false)
{
// Length (Data is checked outside this method)
Assert.Equal(0, entry.Length);
Expand All @@ -190,7 +191,7 @@ protected void SetCommonProperties(TarEntry entry)
entry.Gid = TestGid;

// Mode
Assert.Equal(DefaultMode, entry.Mode);
Assert.Equal(isDirectory ? DefaultDirectoryMode : DefaultFileMode, entry.Mode);
entry.Mode = TestMode;

// MTime: Verify the default value was approximately "now" by default
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public void Add_Fifo(TarEntryFormat format)
string fifoName = "fifofile";
string fifoPath = Path.Join(root.Path, fifoName);

Interop.CheckIo(Interop.Sys.MkFifo(fifoPath, (int)DefaultMode));
Interop.CheckIo(Interop.Sys.MkFifo(fifoPath, (int)DefaultFileMode));

using MemoryStream archive = new MemoryStream();
using (TarWriter writer = new TarWriter(archive, expectedFormat, leaveOpen: true))
Expand Down Expand Up @@ -65,7 +65,7 @@ public void Add_BlockDevice(TarEntryFormat format)
string blockDevicePath = Path.Join(root.Path, AssetBlockDeviceFileName);

// Creating device files needs elevation
Interop.CheckIo(Interop.Sys.CreateBlockDevice(blockDevicePath, (int)DefaultMode, TestBlockDeviceMajor, TestBlockDeviceMinor));
Interop.CheckIo(Interop.Sys.CreateBlockDevice(blockDevicePath, (int)DefaultFileMode, TestBlockDeviceMajor, TestBlockDeviceMinor));

using MemoryStream archive = new MemoryStream();
using (TarWriter writer = new TarWriter(archive, expectedFormat, leaveOpen: true))
Expand Down Expand Up @@ -109,7 +109,7 @@ public void Add_CharacterDevice(TarEntryFormat format)
string characterDevicePath = Path.Join(root.Path, AssetCharacterDeviceFileName);

// Creating device files needs elevation
Interop.CheckIo(Interop.Sys.CreateCharacterDevice(characterDevicePath, (int)DefaultMode, TestCharacterDeviceMajor, TestCharacterDeviceMinor));
Interop.CheckIo(Interop.Sys.CreateCharacterDevice(characterDevicePath, (int)DefaultFileMode, TestCharacterDeviceMajor, TestCharacterDeviceMinor));

using MemoryStream archive = new MemoryStream();
using (TarWriter writer = new TarWriter(archive, expectedFormat, leaveOpen: true))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public void Add_Fifo_Async(TarEntryFormat format)
string fifoName = "fifofile";
string fifoPath = Path.Join(root.Path, fifoName);

Interop.CheckIo(Interop.Sys.MkFifo(fifoPath, (int)DefaultMode));
Interop.CheckIo(Interop.Sys.MkFifo(fifoPath, (int)DefaultFileMode));

await using (MemoryStream archive = new MemoryStream())
{
Expand Down Expand Up @@ -70,7 +70,7 @@ public void Add_BlockDevice_Async(TarEntryFormat format)
string blockDevicePath = Path.Join(root.Path, AssetBlockDeviceFileName);

// Creating device files needs elevation
Interop.CheckIo(Interop.Sys.CreateBlockDevice(blockDevicePath, (int)DefaultMode, TestBlockDeviceMajor, TestBlockDeviceMinor));
Interop.CheckIo(Interop.Sys.CreateBlockDevice(blockDevicePath, (int)DefaultFileMode, TestBlockDeviceMajor, TestBlockDeviceMinor));

await using (MemoryStream archive = new MemoryStream())
{
Expand Down Expand Up @@ -117,7 +117,7 @@ public void Add_CharacterDevice_Async(TarEntryFormat format)
string characterDevicePath = Path.Join(root.Path, AssetCharacterDeviceFileName);

// Creating device files needs elevation
Interop.CheckIo(Interop.Sys.CreateCharacterDevice(characterDevicePath, (int)DefaultMode, TestCharacterDeviceMajor, TestCharacterDeviceMinor));
Interop.CheckIo(Interop.Sys.CreateCharacterDevice(characterDevicePath, (int)DefaultFileMode, TestCharacterDeviceMajor, TestCharacterDeviceMinor));

await using (MemoryStream archive = new MemoryStream())
{
Expand Down

0 comments on commit 502507a

Please sign in to comment.