GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Fix unixmode to handle setuid/sticky when not executable by JamesWTruher · Pull Request #20366 · PowerShell/PowerShell

Fix unixmode to handle setuid/sticky when not executable #20366

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.

Sign up for GitHub

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
Dongbo Wang (daxian-dbw) merged 9 commits into PowerShell:master from JamesWTruher:UnixModeStringFix01
Oct 11, 2023

Uh oh!

There was an error while loading. Please reload this page.

Merged

Fix unixmode to handle setuid/sticky when not executable #20366

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
9 commits
Select commit Hold shift + click to select a range
fee81e8
Change the way the mode string is created on Unix system.
JamesWTruher Sep 21, 2023
205a65e
Add tests to cover more modes.
JamesWTruher Sep 25, 2023
5631c6f
Add comment to explain why we check for chmod success.
JamesWTruher Sep 25, 2023
fcc5c17
Update test/powershell/Modules/Microsoft.PowerShell.Management/UnixSt…
JamesWTruher Sep 28, 2023
b2959a0
Reduce allocations by providing some common mode strings as constants.
JamesWTruher Oct 2, 2023
4f1d4fb
Revert "Reduce allocations by providing some common mode strings as c…
JamesWTruher Oct 2, 2023
cb92b5f
Reduce allocations by providing some common mode strings as constants.
JamesWTruher Oct 3, 2023
ef7e0a8
Update src/System.Management.Automation/CoreCLR/CorePsPlatform.cs
JamesWTruher Oct 11, 2023
70292b0
Update src/System.Management.Automation/CoreCLR/CorePsPlatform.cs
JamesWTruher Oct 11, 2023
File filter
Filter by extension

Clear filters
Conversations
Failed to load comments.
Loading

Uh oh!

There was an error while loading. Please reload this page.

Jump to
Jump to file
Failed to load files.
Loading

Uh oh!

There was an error while loading. Please reload this page.

Diff view
Diff view

There are no files selected for viewing

109 changes: 48 additions & 61 deletions 109 src/System.Management.Automation/CoreCLR/CorePsPlatform.cs
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -594,82 +594,69 @@ public class CommonStat
private const char CanRead = 'r';
private const char CanWrite = 'w';
private const char CanExecute = 'x';

// helper for getting unix mode
private readonly Dictionary<StatMask, char> modeMap = new()
{
{ StatMask.OwnerRead, CanRead },
{ StatMask.OwnerWrite, CanWrite },
{ StatMask.OwnerExecute, CanExecute },
{ StatMask.GroupRead, CanRead },
{ StatMask.GroupWrite, CanWrite },
{ StatMask.GroupExecute, CanExecute },
{ StatMask.OtherRead, CanRead },
{ StatMask.OtherWrite, CanWrite },
{ StatMask.OtherExecute, CanExecute },
};

private readonly StatMask[] permissions = new StatMask[]
{
StatMask.OwnerRead,
StatMask.OwnerWrite,
StatMask.OwnerExecute,
StatMask.GroupRead,
StatMask.GroupWrite,
StatMask.GroupExecute,
StatMask.OtherRead,
StatMask.OtherWrite,
StatMask.OtherExecute
};
private const char NoPerm = '-';
private const char SetAndExec = 's';
private const char SetAndNotExec = 'S';
private const char StickyAndExec = 't';
private const char StickyAndNotExec = 'T';

// The item type and the character representation for the first element in the stat string
private readonly Dictionary<ItemType, char> itemTypeTable = new()
private static readonly Dictionary<ItemType, char> itemTypeTable = new()
{
{ ItemType.BlockDevice, 'b' },
{ ItemType.BlockDevice, 'b' },
{ ItemType.CharacterDevice, 'c' },
{ ItemType.Directory, 'd' },
{ ItemType.File, '-' },
{ ItemType.NamedPipe, 'p' },
{ ItemType.Socket, 's' },
{ ItemType.SymbolicLink, 'l' },
{ ItemType.Directory, 'd' },
{ ItemType.File, '-' },
{ ItemType.NamedPipe, 'p' },
{ ItemType.Socket, 's' },
{ ItemType.SymbolicLink, 'l' },
};

// We'll create a few common mode strings here to reduce allocations and improve performance a bit.
private const string OwnerReadGroupReadOtherRead = "-r--r--r--";
private const string OwnerReadWriteGroupReadOtherRead = "-rw-r--r--";
private const string DirectoryOwnerFullGroupReadExecOtherReadExec = "drwxr-xr-x";

/// <summary>Convert the mode to a string which is usable in our formatting.</summary>
/// <returns>The mode converted into a Unix style string similar to the output of ls.</returns>
public string GetModeString()
{
int offset = 0;
char[] modeCharacters = new char[10];
modeCharacters[offset++] = itemTypeTable[ItemType];
// On an Ubuntu system (docker), these 3 are roughly 70% of all the permissions
if ((Mode & 0xFFF) == 292)
Comment thread
JamesWTruher marked this conversation as resolved.
Resolved

Uh oh!

There was an error while loading. Please reload this page.

{
return OwnerReadGroupReadOtherRead;
}

foreach (StatMask permission in permissions)
if ((Mode & 0xFFF) == 420)
{
// determine whether we are setuid, sticky, or the usual rwx.
if ((Mode & (int)permission) == (int)permission)
{
if ((permission == StatMask.OwnerExecute && IsSetUid) || (permission == StatMask.GroupExecute && IsSetGid))
{
// Check for setuid and add 's'
modeCharacters[offset] = 's';
}
else if (permission == StatMask.OtherExecute && IsSticky && (ItemType == ItemType.Directory))
{
// Directories are sticky, rather than setuid
modeCharacters[offset] = 't';
}
else
{
modeCharacters[offset] = modeMap[permission];
}
}
else
{
modeCharacters[offset] = '-';
}
return OwnerReadWriteGroupReadOtherRead;
}

offset++;
if (ItemType == ItemType.Directory & (Mode & 0xFFF) == 493)
{
return DirectoryOwnerFullGroupReadExecOtherReadExec;
}

Span<char> modeCharacters = stackalloc char[10];
modeCharacters[0] = itemTypeTable[ItemType];
bool isExecutable;

UnixFileMode modeInfo = (UnixFileMode)Mode;
modeCharacters[1] = modeInfo.HasFlag(UnixFileMode.UserRead) ? CanRead : NoPerm;
modeCharacters[2] = modeInfo.HasFlag(UnixFileMode.UserWrite) ? CanWrite : NoPerm;
isExecutable = modeInfo.HasFlag(UnixFileMode.UserExecute);
modeCharacters[3] = modeInfo.HasFlag(UnixFileMode.SetUser) ? (isExecutable ? SetAndExec : SetAndNotExec) : (isExecutable ? CanExecute : NoPerm);

modeCharacters[4] = modeInfo.HasFlag(UnixFileMode.GroupRead) ? CanRead : NoPerm;
modeCharacters[5] = modeInfo.HasFlag(UnixFileMode.GroupWrite) ? CanWrite : NoPerm;
isExecutable = modeInfo.HasFlag(UnixFileMode.GroupExecute);
modeCharacters[6] = modeInfo.HasFlag(UnixFileMode.SetGroup) ? (isExecutable ? SetAndExec : SetAndNotExec) : (isExecutable ? CanExecute : NoPerm);

modeCharacters[7] = modeInfo.HasFlag(UnixFileMode.OtherRead) ? CanRead : NoPerm;
modeCharacters[8] = modeInfo.HasFlag(UnixFileMode.OtherWrite) ? CanWrite : NoPerm;
isExecutable = modeInfo.HasFlag(UnixFileMode.OtherExecute);
modeCharacters[9] = modeInfo.HasFlag(UnixFileMode.StickyBit) ? (isExecutable ? StickyAndExec : StickyAndNotExec) : (isExecutable ? CanExecute : NoPerm);

return new string(modeCharacters);
}

Expand Down
15 changes: 13 additions & 2 deletions 15 test/powershell/Modules/Microsoft.PowerShell.Management/UnixStat.Tests.ps1
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ Describe "UnixFileSystem additions" -Tag "CI" {
@{ Mode = '555'; Perm = '-r-xr-xr-x'; Item = "${testFile}" },
@{ Mode = '666'; Perm = '-rw-rw-rw-'; Item = "${testFile}" },
@{ Mode = '777'; Perm = '-rwxrwxrwx'; Item = "${testFile}" },
@{ Mode = '4644'; Perm = '-rwSr--r--'; Item = "${testFile}" },
@{ Mode = '1644'; Perm = '-rw-r--r-T'; Item = "${testFile}" },
@{ Mode = '2644'; Perm = '-rw-r-Sr--'; Item = "${testFile}" },
@{ Mode = '7644'; Perm = '-rwSr-Sr-T'; Item = "${testFile}" },
@{ Mode = '4777'; Perm = '-rwsrwxrwx'; Item = "${testFile}" },
@{ Mode = '1777'; Perm = 'drwxrwxrwt'; Item = "${testDir}" }
}
Expand All @@ -57,9 +61,16 @@ Describe "UnixFileSystem additions" -Tag "CI" {

It "Should present filemode '<Mode>' string correctly as '<Perm>'" -testCase $testCase {
param ($Mode, $Perm, $Item )
# chmod can fail for some modes so be sure to handle that here.
# specifically, when setting setgid chmod can fail if the group is privileged.
chmod "$Mode" "${Item}"
$i = Get-Item $Item
$i.UnixMode | Should -Be $Perm
if ($LASTEXITCODE -ne 0) {
set-itresult -skip -because "chmod '$mode' failed"
}
else {
$i = Get-Item $Item
$i.UnixMode | Should -BeExactly $Perm
}
}

It "Should retrieve the user name for the file" {
Expand Down
Add this suggestion to a batch that can be applied as a single commit. This suggestion is invalid because no changes were made to the code. Suggestions cannot be applied while the pull request is closed. Suggestions cannot be applied while viewing a subset of changes. Only one suggestion per line can be applied in a batch. Add this suggestion to a batch that can be applied as a single commit. Applying suggestions on deleted lines is not supported. You must change the existing code in this line in order to create a valid suggestion. Outdated suggestions cannot be applied. This suggestion has been applied or marked resolved. Suggestions cannot be applied from pending reviews. Suggestions cannot be applied on multi-line comments. Suggestions cannot be applied while the pull request is queued to merge. Suggestion cannot be applied right now. Please check back later.
You are visitor 01402520 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.