nxtools.psm1
#Region './prefix.ps1' 0 Import-Module -Name $PSScriptRoot\Modules\PSNativeCmdDevKit -ErrorAction Stop #EndRegion './prefix.ps1' 2 #Region './Enum/nxFileSystemAccessRight.ps1' 0 [Flags()] enum nxFileSystemAccessRight { Read = 4 Write = 2 Execute = 1 None = 0 } #EndRegion './Enum/nxFileSystemAccessRight.ps1' 10 #Region './Enum/nxFileSystemItemType.ps1' 0 enum nxFileSystemItemType { File Directory Link Pipe Socket } #EndRegion './Enum/nxFileSystemItemType.ps1' 9 #Region './Enum/nxFileSystemSpecialMode.ps1' 0 [Flags()] enum nxFileSystemSpecialMode { SetUserId = 4 # S_ISUID: Set user ID on execution SetGroupId = 2 # S_ISVTX: Set group ID on execution StickyBit = 1 # S_ISVTX: Sticky bit None = 0 } #EndRegion './Enum/nxFileSystemSpecialMode.ps1' 10 #Region './Enum/nxFileSystemUserClass.ps1' 0 [Flags()] enum nxFileSystemUserClass { User = 4 # u Group = 2 # g Others = 1 # o } #EndRegion './Enum/nxFileSystemUserClass.ps1' 8 #Region './Classes/nxFileSystemInfo.ps1' 0 class nxFileSystemInfo : System.IO.FileSystemInfo { [nxFileSystemMode] $Mode [nxFileSystemItemType] $nxFileSystemItemType [int] $nxLinkCount [System.String] $nxOwner [System.String] $nxGroup [long] $Length [string] $Name [datetime] $LastWriteTime nxFileSystemInfo ([System.Collections.IDictionary]$properties) { Write-Verbose -Message "Creating [nxFileSystemInfo] with path '$($properties.FullPath)'." $this.OriginalPath = $properties.FullPath $this.FullPath = $properties.FullPath $this.SetPropertiesFromIDictionary($properties) $this.Name = [System.Io.Path]::GetFileName($this.FullPath) } hidden [void] SetPropertiesFromIDictionary ([System.Collections.IDictionary]$properties) { Write-Verbose -Message "Setting Propeties from Dictionary." $properties.keys.Foreach{ if ($this.psobject.Properties.name -contains $_) { try { Write-Debug -Message "`tAdding '$_' with value '$($properties[$_])'." $this.($_) = $properties[$_] } catch { Write-Warning -Message $_.Exception.Message } } else { Write-Verbose -Message "The key '$_' is not a property." } } } nxFileSystemInfo([string]$Path) { # ctor $this.OriginalPath = $Path $this.FullPath = [System.IO.Path]::GetFullPath($Path) $this.Name = [System.Io.Path]::GetFileName($this.FullPath) } [void] Delete() { Remove-Item -Path $this.FullName -ErrorAction Stop $this.Dispose() } hidden [string] GetModeWithItemType() { $modeSymbol = $this.Mode.ToString() $typeSymbol = switch ($this.nxFileSystemItemType) { ([nxFileSystemItemType]::File) { '-' } ([nxFileSystemItemType]::Directory) { 'd' } ([nxFileSystemItemType]::Link) { 'l' } ([nxFileSystemItemType]::Socket) { 's' } ([nxFileSystemItemType]::Pipe) { 'p' } } return ('{0}{1}' -f $typeSymbol,$modeSymbol) } } #EndRegion './Classes/nxFileSystemInfo.ps1' 76 #Region './Classes/nxFileSystemMode.ps1' 0 class nxFileSystemMode { hidden static [string] $SymbolicTriadParser = '^[-dlsp]?(?<User>[-wrxsStT]{3})(?<Group>[-wrxsStT]{3})(?<Others>[-wrxsStT]{3})$' hidden static [string] $SymbolicOperationParser = '^(?<userClass>[ugoa]{1,3})(?<operator>[\-\+\=]{1})(?<permissions>[wrxTtSs-]{1,3})$' [nxFileSystemSpecialMode] $SpecialModeFlags [nxFileSystemAccessRight] $OwnerMode [nxFileSystemAccessRight] $GroupMode [nxFileSystemAccessRight] $OthersMode nxFileSystemMode() { # default ctor, can be used like this: <# [nxFileSystemMode]@{ SpecialModeFlags = 'None' OwnerMode = 'Read, Write, Execute' GroupMode = 'Read, Execute' OthersMode = 7 } #> } nxFileSystemMode([String]$Modes) { if ($Modes -match '^\d{3,4}$') { # Convert from Int to nxFileSystemAccessRight $this.setNxFileSystemModeFromInt([int]::Parse($Modes)) } elseif ($Modes -cmatch [nxFileSystemMode]::SymbolicTriadParser) { $this.setNxFileSystemModeFromSymbolicTriadNotation($Modes) } elseif (-not ($Modes -split '\s+').Where{$_ -cnotmatch [nxFileSystemMode]::SymbolicOperationParser}) { # All items of the space delimited Symbolic operations have been checked. $this.DoSymbolicChmodOperation($Modes) } else { throw "The symbolic string '$Modes' is invalid." } } nxFileSystemMode([int]$Modes) { $this.setNxFileSystemModeFromInt($Modes) } hidden [void] setNxFileSystemModeFromSymbolicTriadNotation([string]$SymbolicTriad) { $null = $SymbolicTriad -cmatch [nxFileSystemMode]::SymbolicTriadParser $this.DoSymbolicChmodOperation(@( ('u=' + $Matches['User']) ('g=' + $Matches['Group']) ('o=' + $Matches['Others']) ) -join ' ') } hidden [void] setNxFileSystemModeFromInt([Int]$Modes) { # Adding leading 0s to ensure we have a 0 for the special flags i.e. 777 -> 0777 $StringMode = "{0:0000}" -f $Modes Write-Debug -Message "Trying to parse the permission set expressed by '$($Modes)'." if ($StringMode.Length -gt 4) { throw "Mode set should be expressed with 4 or 3 digits (you can omit the one on the left): setuid(4)/setgid(2)/sticky bit(1)|Owner|Group|Others). '$($StringMode)'" } Write-Debug -Message "Parsing Special Mode Flags: $([int]::Parse($StringMode[0]))" $this.SpecialModeFlags = [int]::Parse($StringMode[0]) $this.OwnerMode = [int]::Parse($StringMode[1]) $this.GroupMode = [int]::Parse($StringMode[2]) $this.OthersMode = [int]::Parse($StringMode[3]) } [void] DoChmodOperation ([nxFileSystemUserClass]$UserClass, [char]$Operator, [nxFileSystemAccessRight]$AccessRights, [nxFileSystemSpecialMode]$SpecialMode) { switch ($operator) { '=' { $this.SetMode($userClass, $accessRights, $specialMode) } '+' { $this.AddMode($userClass, $accessRights, $specialMode) } '-' { $this.RemoveMode($userClass, $accessRights, $specialMode) } default { throw "Operator not recognised '$operator'." } } } [void] DoSymbolicChmodOperation ([string]$SymbolicChmodString) { $symbolicChmodList = $SymbolicChmodString -split '\s+' foreach ($symbolicChmodStringItem in $symbolicChmodList) { Write-Debug -Message "Doing Symbolic Operation '$symbolicChmodStringItem'." if ($symbolicChmodStringItem -match [nxFileSystemMode]::SymbolicOperationParser) { $userClassChars = $Matches['userClass'] $operator = $Matches['operator'] $permissions = $Matches['permissions'] $userClass = [nxFileSystemUserClass](Convert-nxSymbolToFileSystemUserClass -Char $userClassChars) Write-Debug -Message "Parsing $permissions" $specialMode = [nxFileSystemSpecialMode](Convert-nxSymbolToFileSystemSpecialMode -SpecialModeSymbol $permissions -UserClass $UserClass) $accessRights = [nxFileSystemAccessRight](Convert-nxSymbolToFileSystemAccessRight -AccessRightSymbol $permissions) $this.DoChmodOperation($userClass, $operator, $accessRights, $specialMode) } } } [void] SetMode ([nxFileSystemUserClass]$UserClass, [nxFileSystemAccessRight]$AccessRights, [nxFileSystemSpecialMode]$SpecialMode) { Write-Debug -Message "Setting rights '$($AccessRights)' and special flag '$($SpecialMode)' to '$($UserClass)'" switch ($UserClass) { { $_ -band [nxFileSystemUserClass]::User } { $this.OwnerMode = $AccessRights } { $_ -band [nxFileSystemUserClass]::Group } { $this.GroupMode = $AccessRights } { $_ -band [nxFileSystemUserClass]::Others } { $this.OthersMode = $AccessRights } default { throw "Error with unrecognized User Class '$UserClass'." } } $this.SpecialModeFlags = $SpecialMode } [void] AddMode ([nxFileSystemUserClass]$UserClass, [nxFileSystemAccessRight]$AccessRights, [nxFileSystemSpecialMode]$SpecialMode) { Write-Debug -Message "Adding rights '$($AccessRights)' and special flag '$($SpecialMode)' to '$($UserClass)'" switch ($UserClass) { { $_ -band [nxFileSystemUserClass]::User } { $this.OwnerMode = $this.OwnerMode -bor $AccessRights } { $_ -band [nxFileSystemUserClass]::Group } { $this.GroupMode = $this.GroupMode -bor $AccessRights } { $_ -band [nxFileSystemUserClass]::Others } { $this.OthersMode = $this.OthersMode -bor $AccessRights } default { throw "Error with unrecognized User Class '$UserClass'." } } $this.SpecialModeFlags = $this.SpecialModeFlags -bor $SpecialMode } [void] RemoveMode ([nxFileSystemUserClass]$UserClass, [nxFileSystemAccessRight]$AccessRights, [nxFileSystemSpecialMode]$SpecialMode) { Write-Debug -Message "Removing rights '$($AccessRights)' and special flag '$($SpecialMode)' to '$($UserClass)'" switch ($UserClass) { { $_ -band [nxFileSystemUserClass]::User } { $this.OwnerMode = $this.OwnerMode -band -bnot $AccessRights } { $_ -band [nxFileSystemUserClass]::Group } { $this.GroupMode = $this.GroupMode -band -bnot $AccessRights } { $_ -band [nxFileSystemUserClass]::Others } { $this.OthersMode = $this.OthersMode -band -bnot $AccessRights } default { throw "Error with unrecognized User Class '$UserClass'." } } $this.SpecialModeFlags = $this.SpecialModeFlags -band -bnot $SpecialMode } [string] ToString() { Write-Verbose -Message "$($this.OwnerMode)" Write-Verbose -Message "$(@($this.OthersMode, $this.SpecialModeFlags) -join '|')" $SymbolNotation = [PSCustomObject]@{ UserClass = [nxFileSystemUserClass]::User AccessRight = $this.OwnerMode UseDashWhenAbsent = $true }, [PSCustomObject]@{ UserClass = [nxFileSystemUserClass]::Group AccessRight = $this.GroupMode UseDashWhenAbsent = $true }, [PSCustomObject]@{ UserClass = [nxFileSystemUserClass]::User AccessRight = $this.OthersMode UseDashWhenAbsent = $true } | Convert-nxFileSystemAccessRightToSymbol Write-Verbose -Message "SymbolNotation: $SymbolNotation" return ($SymbolNotation -join '') } [string] ToOctal() { return ('{0}{1}{2}{3}' -f ( ([int]$this.SpecialModeFlags), ([int]$this.OwnerMode), ([int]$this.GroupMode), ([int]$this.OthersMode) )) } } #EndRegion './Classes/nxFileSystemMode.ps1' 236 #Region './Classes/nxLocalGroup.ps1' 0 class nxLocalGroup { hidden static $GroupEntryParser = '^(?<groupname>[^:]+):(?<pwd>[^:]*):(?<gid>[\d]+):(?<members>.*)$' [string] $GroupName [string] $Password [int] $GroupId [string[]] $GroupMember nxLocalGroup() { # default ctor } nxLocalGroup([string]$GroupEntry) { Write-Debug -Message "[nxLocalGroup] Parsing '$_'." if ($groupEntry -notmatch [nxLocalGroup]::GroupEntryParser) { throw "Unrecognized Group entry from /etc/group with '($GroupEntry)'." } else { $this.GroupName = $Matches.groupname $this.Password = $Matches.pwd $this.GroupId = [int]::Parse($Matches.gid) $this.GroupMember = $Matches.members -split ',' } } [System.String] ToString() { return $this.GroupName } } #EndRegion './Classes/nxLocalGroup.ps1' 35 #Region './Classes/nxLocalUser.ps1' 0 class nxLocalUser { # gcolas:x:1000:1000:,,,:/home/gcolas:/bin/bash static [regex] $PasswordLineParser = @( '^(?<username>[a-z_]([a-z0-9_-]{0,31}|[a-z0-9_-]{0,30}\$))' '(?<password>[^:]+)' '(?<userid>[\d]+)' '(?<groupid>[\d]+)' '(?<userinfo>[^:]*)' '(?<homedir>[^:]*)' '(?<shellcmd>[^:]*)' ) -join ':' hidden [bool] $HasBeenUpdated = $false [string] $UserName [string] $Password [int] $UserId [int] $GroupId [string] $UserInfo [string] $HomeDirectory [string] $ShellCommand nxLocalUser() { # default ctor } nxLocalUser([System.String]$passwdEntry) { Write-Debug -Message "[nxLocalUser] Parsing '$_'." if ($passwdEntry -notmatch [nxLocalUser]::PasswordLineParser) { throw "Unrecognised passwd entry: '$passwdEntry'." } $this.UserName = $Matches.username $this.Password = $Matches.password $this.UserId = [int]::Parse($Matches.userid) $this.GroupId = [int]::Parse($Matches.groupid) $this.UserInfo = $Matches.userinfo $this.HomeDirectory = $Matches.homedir $this.ShellCommand = $Matches.shellcmd $this | Add-Member -PassThru -MemberType ScriptProperty -Name MemberOf -Value { # only calling the method when needed to avoid unecessary calls $this.GetMemberOf() } } static [bool] Exists([string]$UserName) { $result = Invoke-NativeCommand -Executable 'id' -Parameters @('-u', $UserName) [int]$ParsedUserID = -1 if ([int]::TryParse($result, [ref]$ParsedUserID)) { Write-Debug -Message "User id for '$UserName' is '$result'." return $true } else { return $false } } [string] ToString() { return $this.UserName } [void] Save() { if ([nxLocalUser]::Exists($this.Username)) { $this.Update() } else { $this.SaveAsNewNxLocalAccount() } } [void] Update() { $this | Set-nxLocalUser } [void] SaveAsNewNxLocalAccount() { $newUser = $this | Add-nxLocalUser } [nxLocalGroup[]] GetMemberOf() { return (Get-nxLocalUserMemberOf -User $this.UserName).MemberOf } } #EndRegion './Classes/nxLocalUser.ps1' 99 #Region './Private/Get-nxSourceFile.ps1' 0 function Get-nxSourceFile { [CmdletBinding()] [OutputType([void])] param ( [Parameter(Mandatory = $true)] [System.String] [ValidateScript({$_ -as [uri] -or (Test-Path -Path $_ -PathType Leaf)})] [Alias('Uri')] $Path, [Parameter()] [System.String] $DestinationFile, [Parameter()] [System.Management.Automation.SwitchParameter] $Force ) if (Test-Path -Path $DestinationFile) { if ($Force) { Remove-Item -Force -Recurse -Path $DestinationFile } else { throw ('File ''{0}'' already exists.' -f $DestinationFile) } } if ($Path -as [uri] -and ([uri]$Path).Scheme -match '^http|^ftp') { $null = Invoke-WebRequest -Uri $Path -OutFile $DestinationFile -ErrorAction 'Stop' } else { Copy-Item -Path $Path -Destination $DestinationFile -ErrorAction Stop -Force:$Force } } #EndRegion './Private/Get-nxSourceFile.ps1' 42 #Region './Private/nxFileSystem/Convert-nxFileSystemAccessRightToSymbol.ps1' 0 function Convert-nxFileSystemAccessRightToSymbol { [CmdletBinding()] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [System.String[]] [ValidateScript({$_ -as [nxFileSystemAccessRight] -or $_ -as [nxFileSystemSpecialMode]})] $AccessRight, [Parameter(ValueFromPipelineByPropertyName = $true)] [nxFileSystemUserClass] [Alias('Class')] $UserClass, [Parameter(ValueFromPipelineByPropertyName = $true)] [System.Management.Automation.SwitchParameter] $UseDashWhenAbsent ) process { Write-Verbose "Access Right: '$($AccessRight -join "', '")'" [nxFileSystemAccessRight]$AccessRightEntry = 'none' [nxFileSystemSpecialMode]$SpecialModeEntry = 'none' $AccessRight.ForEach({ if ($_ -as [nxFileSystemAccessRight]) { $AccessRightEntry = $AccessRightEntry -bor [nxFileSystemAccessRight]$_ } elseif ($_ -as [nxFileSystemSpecialMode]) { $SpecialModeEntry = $SpecialModeEntry -bor [nxFileSystemSpecialMode]$_ } }) Write-Debug -Message "AccessRight: '$AccessRightEntry', SpecialMode: $SpecialModeEntry" $Symbols = @( $AccessRightEntry -band [nxFileSystemAccessRight]::Read ? 'r' : ($UseDashWhenAbsent ? '-':'') $AccessRightEntry -band [nxFileSystemAccessRight]::Write ? 'w' : ($UseDashWhenAbsent ? '-':'') if ( $UserClass -band [nxFileSystemUserClass]::Group -and $SpecialModeEntry -band [nxFileSystemSpecialMode]::SetGroupId -and $AccessRightEntry -band [nxFileSystemAccessRight]::Execute ) { 's' } elseif ( $UserClass -band [nxFileSystemUserClass]::Group -and $SpecialModeEntry -band [nxFileSystemSpecialMode]::SetGroupId ) { 'S' } elseif ( $UserClass -band [nxFileSystemUserClass]::User -and $SpecialModeEntry -band [nxFileSystemSpecialMode]::SetUserId -and $AccessRightEntry -band [nxFileSystemAccessRight]::Execute ) { 's' } elseif ( $UserClass -band [nxFileSystemUserClass]::User -and $SpecialModeEntry -band [nxFileSystemSpecialMode]::SetUserId ) { 'S' } elseif ( $UserClass -band [nxFileSystemUserClass]::Others -and $SpecialModeEntry -band [nxFileSystemSpecialMode]::StickyBit -and $AccessRightEntry -band [nxFileSystemAccessRight]::Execute ) { 't' } elseif ( $UserClass -band [nxFileSystemUserClass]::Others -and $SpecialModeEntry -band [nxFileSystemSpecialMode]::StickyBit ) { 'T' } elseif ($AccessRightEntry -band [nxFileSystemAccessRight]::Execute) { 'x' } elseif ($UseDashWhenAbsent) { '-' } ) Write-Verbose -Message "Symbols: '$($Symbols -join '')'." ($Symbols -join '') } } #EndRegion './Private/nxFileSystem/Convert-nxFileSystemAccessRightToSymbol.ps1' 104 #Region './Private/nxFileSystem/Convert-nxFileSystemModeComparisonToSymbolicOperation.ps1' 0 function Convert-nxFileSystemModeComparisonToSymbolicOperation { [CmdletBinding()] [OutputType([string])] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('Class')] [nxFileSystemUserClass] $UserClass, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [System.String] [ValidateScript({$_ -as [nxFileSystemAccessRight] -or $_ -as [nxFileSystemSpecialMode]})] [Alias('InputObject')] $EnumValue, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [string] $SideIndicator ) process { # FTR the side indicator points where the EnumValue is found: REFERENCE <=> DIFFERENCE # The SympolicOperation generated aims to make the DifferenceMode compliante with the reference. Write-Debug "[$UserClass] [$EnumValue] [$SideIndicator]" if ($SideIndicator -eq '<=') { # Need to add something that is not in the reference $operator = '+' } else { # Need to remove something that is not in the reference $operator = '-' } $UserClassSymbol = Convert-nxFileSystemUserClassToSymbol -UserClass $UserClass $ModeSymbol = Convert-nxFileSystemAccessRightToSymbol -AccessRight $EnumValue -UserClass $UserClass return ('{0}{1}{2}' -f $UserClassSymbol, $operator, $ModeSymbol) } } #EndRegion './Private/nxFileSystem/Convert-nxFileSystemModeComparisonToSymbolicOperation.ps1' 46 #Region './Private/nxFileSystem/Convert-nxFileSystemUserClassToSymbol.ps1' 0 function Convert-nxFileSystemUserClassToSymbol { [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory = $true)] [nxFileSystemUserClass] [Alias('Class')] $UserClass ) $symbols = switch ($UserClass) { ([nxFileSystemUserClass]::User) { 'u' } ([nxFileSystemUserClass]::Group) { 'g' } ([nxFileSystemUserClass]::Others) { 'o' } } return ($symbols -join '') } #EndRegion './Private/nxFileSystem/Convert-nxFileSystemUserClassToSymbol.ps1' 22 #Region './Private/nxFileSystem/Convert-nxLsEntryToFileSystemInfo.ps1' 0 function Convert-nxLsEntryToFileSystemInfo { param ( [Parameter(ValueFromPipeline = $true)] [System.String] $lsLine, [Parameter()] [System.String] $InitialPath = '.', [Parameter()] [scriptblock] $ErrorHandler = { switch -Regex ($_) { default { Write-Error "$_" } } } ) begin { $lastParent = $null } process { foreach ($lineToParse in $lsLine.Where{$_}) { Write-Verbose -Message "Parsing ls line output: '$lineToParse'." if ($lineToParse -is [System.Management.Automation.ErrorRecord]) { $lineToParse | &$ErrorHandler } elseif ($lineToParse -match 'Access denied|No such file or directory') { throw $lineToParse } elseif ($lineToParse -match '^\s*total') { Write-Verbose -Message $lineToParse } elseif ($lineToParse -match '^(?<parent>/.*):$') { $lastParent = $Matches.parent } else { $Mode, $nxLinkCount, $nxOwner, $nxGroup, $Length, $lastModifyDate, $lastModifyTime, $lastModifyTimezone, $fileName = $lineToParse -split '\s+',9 $nxFileSystemItemType = switch ($Mode[0]) { '-' { 'File' } 'd' { 'Directory' } 'l' { 'Link' } 'p' { 'Pipe' } 's' { 'socket' } } $lastWriteTime = Get-Date -Date ($lastModifyDate + " " + $lastModifyTime + $lastModifyTimezone) # Maybe there's no $lastParent yet (top folder from search Path) if ($null -eq $lastParent) { if ($InitialPath -eq [io.Path]::GetFullPath($fileName, $PWD.Path)) { Write-Debug -Message "No `$lastParent and Initial path is '$InitialPath' same as file name is '$fileName'." # no Last parent and the InitialPath is the same as the file Name. (i.e. ./CHANGELOG.md or CHANGELOG.md) $lastParent = [io.path]::GetFullPath("$InitialPath/..") } else { $lastParent = [io.Path]::GetFullPath($InitialPath) } $fullPath = [io.Path]::GetFullPath($fileName, $lastParent) } else { Write-Debug -Message "`$lastParent is '$lastParent', Initial Path is '$InitialPath' and file name is '$fileName'." $fullPath = [io.path]::GetFullPath($fileName, $lastParent) } [nxFileSystemInfo]::new( @{ FullPath = $fullPath LastWriteTime = $lastWriteTime nxFileSystemItemType = $nxFileSystemItemType nxOwner = $nxOwner nxGroup = $nxGroup Length = [long]::Parse($Length) nxLinkCount = $nxLinkCount Mode = $Mode } ) } } } } #EndRegion './Private/nxFileSystem/Convert-nxLsEntryToFileSystemInfo.ps1' 100 #Region './Private/nxFileSystem/Convert-nxSymbolToFileSystemAccessRight.ps1' 0 function Convert-nxSymbolToFileSystemAccessRight { [CmdletBinding()] [OutputType([nxFileSystemAccessRight])] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [Char[]] [Alias('Char')] $AccessRightSymbol ) process { foreach ($charItem in $AccessRightSymbol) { switch -CaseSensitive ($charItem) { 'w' { [nxFileSystemAccessRight]::Write } 'r' { [nxFileSystemAccessRight]::Read } 'x' { [nxFileSystemAccessRight]::Execute } '-' { [nxFileSystemAccessRight]::None } 'T' { Write-Debug -Message "The UpperCase 'T' means there's no Execute right." [nxFileSystemAccessRight]::None } 't' { [nxFileSystemAccessRight]::Execute } 'S' { Write-Debug -Message "The UpperCase 'S' means there's no Execute right." [nxFileSystemAccessRight]::None } 's' { [nxFileSystemAccessRight]::Execute } } } } } #EndRegion './Private/nxFileSystem/Convert-nxSymbolToFileSystemAccessRight.ps1' 63 #Region './Private/nxFileSystem/Convert-nxSymbolToFileSystemSpecialMode.ps1' 0 function Convert-nxSymbolToFileSystemSpecialMode { [CmdletBinding()] [OutputType([nxFileSystemSpecialMode])] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [Char[]] [Alias('Char')] # the possible char are [sStT], but if other values sucha as [rwx-] are passed, we should just ignore them (no special permission). $SpecialModeSymbol, [Parameter(ValueFromPipelineByPropertyName = $true)] [nxFileSystemUserClass] $UserClass ) process { foreach ($charItem in $SpecialModeSymbol) { Write-Debug -Message "Converting '$charItem' to [nxFileSystemSpecialMode]." switch ($charItem) { 't' { Write-Debug -Message "Adding StickyBit." [nxFileSystemSpecialMode]::StickyBit } 's' { if ($UserClass -eq [nxFileSystemUserClass]::User) { Write-Debug -Message "Adding SetUserId." [nxFileSystemSpecialMode]::SetUserId } if ($UserClass -band [nxFileSystemUserClass]::Group) { Write-Debug -Message "Adding SetGroupId." [nxFileSystemSpecialMode]::SetGroupId } if ((-not $UserClass -band [nxFileSystemUserClass]::Group) -and (-not $UserClass -eq [nxFileSystemUserClass]::User)) { Write-Warning -Message "Cannot determine whether to set the SUID or SGID because the User class is invalid: '$UserClass'" } } default { Write-Debug -Message "Nothing to return for char '$charItem'." } } } } } #EndRegion './Private/nxFileSystem/Convert-nxSymbolToFileSystemSpecialMode.ps1' 57 #Region './Private/nxFileSystem/Convert-nxSymbolToFileSystemUserClass.ps1' 0 function Convert-nxSymbolToFileSystemUserClass { [CmdletBinding()] [OutputType([nxFileSystemUserClass])] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [char[]] $Char ) process { foreach ($charItem in $char) { switch ($charItem) { 'u' { [nxFileSystemUserClass]'User' } 'g' { [nxFileSystemUserClass]'Group' } 'o' { [nxFileSystemUserClass]'Others' } 'a' { [nxFileSystemUserClass]'User, Group, Others' } default { throw "Unexpected char '$CharItem'" } } } } } #EndRegion './Private/nxFileSystem/Convert-nxSymbolToFileSystemUserClass.ps1' 26 #Region './Public/FileSystem/Compare-nxMode.ps1' 0 function Compare-nxMode { [CmdletBinding()] [OutputType([hashtable])] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [nxFileSystemMode] $ReferenceMode, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [nxFileSystemMode[]] [Alias('Mode')] $DifferenceMode, [Parameter(ValueFromPipelineByPropertyName = $true)] [string] [Alias('FullName', 'Path')] $DifferencePath, [Parameter()] [Switch] $IncludeEqual ) process { foreach ($ModeItem in $DifferenceMode) { Write-Verbose -Message "Comparing '$ReferenceMode' with '$ModeItem'" $diffOwner = $ReferenceMode.OwnerMode -bxor $ModeItem.OwnerMode $diffGroup = $ReferenceMode.GroupMode -bxor $ModeItem.GroupMode $diffOthers = $ReferenceMode.OthersMode -bxor $ModeItem.OthersMode $diffSpecialModeFlags = $ReferenceMode.SpecialModeFlags -bxor $ModeItem.SpecialModeFlags foreach ($enumValue in ([Enum]::GetValues([nxFileSystemAccessRight]).Where({$_ -ne [nxFileSystemAccessRight]::None}))) { if ($diffOwner -band $enumValue) { $sideIndicator = $ReferenceMode.OwnerMode -band $enumValue ? '<=' : '=>' Write-Verbose -Message "[$([nxFileSystemUserClass]::User)]'$enumValue' is only on this side [REF '$sideIndicator' DIFF]." [PSCustomObject]@{ Class = [nxFileSystemUserClass]::User InputObject = $enumValue SideIndicator = $sideIndicator DifferencePath = $DifferencePath } | Add-Member -PassThru -Name RemediationOperation -MemberType ScriptProperty -Value {$this | Convert-nxFileSystemModeComparisonToSymbolicOperation} } elseif ($IncludeEqual) { [PSCustomObject]@{ Class = [nxFileSystemUserClass]::User InputObject = $enumValue SideIndicator = '=' RemediationOperation = '' DifferencePath = $DifferencePath } } if ($diffGroup -band $enumValue) { $sideIndicator = $ReferenceMode.GroupMode -band $enumValue ? '<=' : '=>' Write-Verbose -Message "[$([nxFileSystemUserClass]::Group)]'$enumValue' is only on this side [REF '$sideIndicator' DIFF]." [PSCustomObject]@{ Class = [nxFileSystemUserClass]::Group InputObject = $enumValue SideIndicator = $sideIndicator DifferencePath = $DifferencePath } | Add-Member -PassThru -Name RemediationOperation -MemberType ScriptProperty -Value {$this | Convert-nxFileSystemModeComparisonToSymbolicOperation} } elseif ($IncludeEqual) { [PSCustomObject]@{ Class = [nxFileSystemUserClass]::Group InputObject = $enumValue SideIndicator = '=' RemediationOperation = '' DifferencePath = $DifferencePath } } if ($diffOthers -band $enumValue) { $sideIndicator = $ReferenceMode.OthersMode -band $enumValue ? '<=' : '=>' Write-Verbose -Message "[$([nxFileSystemUserClass]::Others)]'$enumValue' is only on this side [REF '$sideIndicator' DIFF]." [PSCustomObject]@{ Class = [nxFileSystemUserClass]::Others InputObject = $enumValue SideIndicator = $sideIndicator DifferencePath = $DifferencePath } | Add-Member -PassThru -Name RemediationOperation -MemberType ScriptProperty -Value {$this | Convert-nxFileSystemModeComparisonToSymbolicOperation} } elseif ($IncludeEqual) { [PSCustomObject]@{ Class = [nxFileSystemUserClass]::Others InputObject = $enumValue SideIndicator = '=' RemediationOperation = '' DifferencePath = $DifferencePath } } } foreach ($enumValue in ([Enum]::GetValues([nxFileSystemSpecialMode]))) { if ($diffSpecialModeFlags -band $enumValue) { $sideIndicator = $ReferenceMode.SpecialModeFlags -band $enumValue ? '<=' : '=>' Write-Verbose -Message "[$([nxFileSystemUserClass]::None)]'$enumValue' is only on this side [REF '$sideIndicator' DIFF]." [PSCustomObject]@{ Class = [nxFileSystemUserClass]::None InputObject = $enumValue SideIndicator = $sideIndicator DifferencePath = $DifferencePath } | Add-Member -PassThru -Name RemediationOperation -MemberType ScriptProperty -Value {$this | Convert-nxFileSystemModeComparisonToSymbolicOperation} } elseif ($IncludeEqual) { [PSCustomObject]@{ Class = [nxFileSystemUserClass]::None InputObject = $enumValue SideIndicator = '=' RemediationOperation = '' DifferencePath = $DifferencePath } } } } } } #EndRegion './Public/FileSystem/Compare-nxMode.ps1' 132 #Region './Public/FileSystem/Get-nxChildItem.ps1' 0 function Get-nxChildItem { [CmdletBinding(DefaultParameterSetName = 'default')] [OutputType([nxFileSystemInfo[]])] param ( [Parameter(ParameterSetName = 'default' , Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [Parameter(ParameterSetName = 'FilterDirectory' , Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [Parameter(ParameterSetName = 'FilterFile' , Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [System.String[]] $Path = '.', [Parameter(ParameterSetName = 'default' , Position = 1, ValueFromPipelineByPropertyName = $true)] [Parameter(ParameterSetName = 'FilterDirectory' , Position = 1, ValueFromPipelineByPropertyName = $true)] [Parameter(ParameterSetName = 'FilterFile' , Position = 1, ValueFromPipelineByPropertyName = $true)] [Switch] $Recurse, [Parameter(ParameterSetName = 'FilterDirectory' , ValueFromPipelineByPropertyName = $true, Position = 2)] [Switch] $Directory, [Parameter(ParameterSetName = 'FilterFile' , ValueFromPipelineByPropertyName = $true, Position = 2)] [Switch] $File ) begin { $verbose = ($PSBoundParameters.ContainsKey('Verbose') -and $PSBoundParameters.Verbose) -or $VerbosePreference -ne 'SilentlyContinue' $debug = ($PSBoundParameters.ContainsKey('Debug') -and $PSBoundParameters['Debug']) -or $DebugPreference -ne 'SilentlyContinue' $lsParams = @('-Al','--full-time','--group-directories-first') if ($PSBoundParameters.ContainsKey('Recurse') -and $PSboundParameters['Recurse']) { $lsParams += '-R' # Alpine linux does not support --recursive } } process { foreach ($pathItem in $Path.Where{$_}) { $pathItem = [System.IO.Path]::GetFullPath($pathItem, $PWD.Path) $unfilteredListCommand = { Invoke-NativeCommand -Executable 'ls' -Parameters ($lsParams + @($pathItem)) -Verbose:($verbose -or $debug) | Convert-nxLsEntryToFileSystemInfo -InitialPath $pathItem -Verbose:$debug } if ($PSCmdlet.ParameterSetName -eq 'FilterFile' -and $PSBoundParameters['File']) { &$unfilteredListCommand | Where-Object -FilterScript { $_.nxFileSystemItemType -eq [nxFileSystemItemType]::File } } elseif ($PSCmdlet.ParameterSetName -eq 'FilterDirectory' -and $PSBoundParameters['Directory']) { &$unfilteredListCommand | Where-Object -FilterScript { $_.nxFileSystemItemType -eq [nxFileSystemItemType]::Directory } } else { &$unfilteredListCommand } } } } #EndRegion './Public/FileSystem/Get-nxChildItem.ps1' 65 #Region './Public/FileSystem/Get-nxItem.ps1' 0 function Get-nxItem { param ( [Parameter(ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true)] [System.String[]] $Path = '.' ) begin { $verbose = ($PSBoundParameters.ContainsKey('Verbose') -and $PSBoundParameters['Verbose']) -or $VerbosePreference -ne 'SilentlyContinue' $debug = ($PSBoundParameters.ContainsKey('Debug') -and $PSBoundParameters['Debug']) -or $DebugPreference -ne 'SilentlyContinue' $lsParams = @('-Al','--full-time','--group-directories-first','-d') } process { foreach ($pathItem in $Path.Where{$_}) { $pathItem = [System.IO.Path]::GetFullPath($pathItem, $PWD.Path) Invoke-NativeCommand -Executable 'ls' -Parameters ($lsParams + @($pathItem)) -Verbose:($verbose -or $debug) | Convert-nxLsEntryToFileSystemInfo -InitialPath $pathItem -Verbose:$debug } } } #EndRegion './Public/FileSystem/Get-nxItem.ps1' 27 #Region './Public/FileSystem/Set-nxGroupOwnership.ps1' 0 function Set-nxGroupOwnership { [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium', DefaultParameterSetName = 'Default')] [OutputType([void])] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'Default', Position = 0)] [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursiveAll', Position = 0)] [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursivePath', Position = 0)] [System.String[]] $Path, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'Default', Position = 1)] [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursiveAll', Position = 1)] [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursivePath', Position = 1)] [ValidateNotNullOrEmpty()] [string] $Group, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'Default')] [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursiveAll')] [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursivePath')] [System.Management.Automation.SwitchParameter] # affect each symbolic link instead of any referenced file (useful only on systems that can change the ownership of a symlink) # -h $NoDereference, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'Default')] [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursiveAll')] [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursivePath')] [System.Management.Automation.SwitchParameter] # Do not traverse any symbolic links by default $Recurse, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursiveAll')] [System.Management.Automation.SwitchParameter] # Traverse every symbolic link to a directory encountered # -L $RecursivelyTraverseSymLink, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursivePath')] [System.Management.Automation.SwitchParameter] # If $Path is a symbolic link to a directory, traverse it. # -H $OnlyTraversePathIfSymLink, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'Default')] [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursiveAll')] [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursivePath')] [System.Management.Automation.SwitchParameter] # Disable root preservation security. $Force ) begin { $verbose = ($PSBoundParameters.ContainsKey('Verbose') -and $PSBoundParameters.Verbose) -or $VerbosePreference -ne 'SilentlyContinue' } process { foreach ($pathItem in $Path) { $pathItem = [System.Io.Path]::GetFullPath($pathItem, $PWD.Path) $chgrpParams = @() if ($PSBoundParameters.ContainsKey('NoDereference') -and $PSBoundParameters['NoDereference']) { $chgrpParams += '-h' } if ($PSBoundParameters.ContainsKey('RecursivelyTraverseSymLink') -and $PSBoundParameters['RecursivelyTraverseSymLink']) { $chgrpParams += '-L' } if ($PSBoundParameters.ContainsKey('OnlyTraversePathIfSymLink') -and $PSBoundParameters['OnlyTraversePathIfSymLink']) { $chgrpParams += '-H' } if ($PSBoundParameters.ContainsKey('Recurse') -and $PSBoundParameters['Recurse']) { $chgrpParams += '-R' } $chgrpParams = ($chgrpParams + @($Group, $pathItem)) if ( $PSCmdlet.ShouldProcess("Performing the unix command 'chgrp $($chgrpParams -join ' ')'.", $PathItem, "chgrp $($chgrpParams -join ' ')") ) { if ($pathItem -eq '/' -and -not ($PSBoundParameters.ContainsKey('Force') -and $Force)) { # can't use the built-in --preserve-root because it's not available on Alpine linux Write-Warning "You are about to chgrp your root. Please use -Force." return } Write-Verbose -Message ('chgrp {0}' -f ($chgrpParams -join ' ')) Invoke-NativeCommand -Executable 'chgrp' -Parameters $chgrpParams -Verbose:$verbose | Foreach-Object -Process { Write-Error -Message $_ } } } } } #EndRegion './Public/FileSystem/Set-nxGroupOwnership.ps1' 107 #Region './Public/FileSystem/Set-nxMode.ps1' 0 function Set-nxMode { [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium', DefaultParameterSetName = 'Default')] [OutputType([void])] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'Default', Position = 0)] [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursiveAll', Position = 0)] [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursivePath', Position = 0)] [System.String[]] $Path, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'Default', Position = 1)] [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursiveAll', Position = 1)] [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursivePath', Position = 1)] [nxFileSystemMode] $Mode, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'Default')] [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursiveAll')] [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursivePath')] [System.Management.Automation.SwitchParameter] # affect each symbolic link instead of any referenced file (useful only on systems that can change the ownership of a symlink) # -h $NoDereference, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'Default')] [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursiveAll')] [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursivePath')] [System.Management.Automation.SwitchParameter] # Do not traverse any symbolic links by default $Recurse, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursiveAll')] [System.Management.Automation.SwitchParameter] # Traverse every symbolic link to a directory encountered # -L $RecursivelyTraverseSymLink, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursivePath')] [System.Management.Automation.SwitchParameter] # If $Path is a symbolic link to a directory, traverse it. # -H $OnlyTraversePathIfSymLink, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'Default')] [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursiveAll')] [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursivePath')] [System.Management.Automation.SwitchParameter] # Disable root preservation security. $Force ) begin { $verbose = ($PSBoundParameters.ContainsKey('Verbose') -and $PSBoundParameters.Verbose) -or $VerbosePreference -ne 'SilentlyContinue' } process { foreach ($pathItem in $Path) { $pathItem = [System.Io.Path]::GetFullPath($pathItem, $PWD.Path) $chmodParams = @() if ($PSBoundParameters.ContainsKey('NoDereference') -and $PSBoundParameters['NoDereference']) { $chmodParams += '-h' } if ($PSBoundParameters.ContainsKey('RecursivelyTraverseSymLink') -and $PSBoundParameters['RecursivelyTraverseSymLink']) { $chmodParams += '-L' } if ($PSBoundParameters.ContainsKey('OnlyTraversePathIfSymLink') -and $PSBoundParameters['OnlyTraversePathIfSymLink']) { $chmodParams += '-H' } if ($PSBoundParameters.ContainsKey('Recurse') -and $PSBoundParameters['Recurse']) { $chmodParams += '-R' } $OctalMode = $Mode.ToOctal() $chmodParams = ($chmodParams + @($OctalMode, $pathItem)) Write-Debug "Parameter Set Name: '$($PSCmdlet.ParameterSetName)'." if ( $PSCmdlet.ShouldProcess("Performing the unix command 'chmod $($chmodParams -join ' ')'.", $PathItem, "chmod $($chmodParams -join ' ')") ) { if ($pathItem -eq '/' -and -not ($PSBoundParameters.ContainsKey('Force') -and $Force)) { # can't use the built-in --preserve-root because it's not available on Alpine linux Write-Warning "You are about to chmod your root. Please use -Force." return } Write-Verbose -Message ('chmod {0}' -f ($chmodParams -join ' ')) Invoke-NativeCommand -Executable 'chmod' -Parameters $chmodParams -Verbose:$verbose | Foreach-Object -Process { Write-Error -Message $_ } } } } } #EndRegion './Public/FileSystem/Set-nxMode.ps1' 109 #Region './Public/FileSystem/Set-nxOwner.ps1' 0 function Set-nxOwner { [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium', DefaultParameterSetName = 'Default')] [OutputType([void])] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'Default')] [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursiveAll')] [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursivePath')] [System.String[]] $Path, [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'Default')] [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursiveAll')] [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursivePath')] [ValidateNotNullOrEmpty()] [System.String] [Alias('UserName')] $Owner, [Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'Default')] [Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursiveAll')] [Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursivePath')] [ValidateNotNullOrEmpty()] [string] $Group, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'Default')] [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursiveAll')] [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursivePath')] [System.Management.Automation.SwitchParameter] # affect each symbolic link instead of any referenced file (useful only on systems that can change the ownership of a symlink) # -h $NoDereference, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'Default')] [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursiveAll')] [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursivePath')] [System.Management.Automation.SwitchParameter] # Do not traverse any symbolic links by default $Recurse, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursiveAll')] [System.Management.Automation.SwitchParameter] # Traverse every symbolic link to a directory encountered # -L $RecursivelyTraverseSymLink, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursivePath')] [System.Management.Automation.SwitchParameter] # If $Path is a symbolic link to a directory, traverse it. # -H $OnlyTraversePathIfSymLink, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'Default')] [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursiveAll')] [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'RecursivePath')] [System.Management.Automation.SwitchParameter] # Disable root preservation security. $Force ) begin { $verbose = ($PSBoundParameters.ContainsKey('Verbose') -and $PSBoundParameters.Verbose) -or $VerbosePreference -ne 'SilentlyContinue' } process { foreach ($pathItem in $Path) { $pathItem = [System.Io.Path]::GetFullPath($pathItem, $PWD.Path) $chownParams = @() if ($PSBoundParameters.ContainsKey('NoDereference') -and $PSBoundParameters['NoDereference']) { $chownParams += '-h' } if ($PSBoundParameters.ContainsKey('RecursivelyTraverseSymLink') -and $PSBoundParameters['RecursivelyTraverseSymLink']) { $chownParams += '-L' } if ($PSBoundParameters.ContainsKey('OnlyTraversePathIfSymLink') -and $PSBoundParameters['OnlyTraversePathIfSymLink']) { $chownParams += '-H' } if ($PSBoundParameters.ContainsKey('Recurse') -and $PSBoundParameters['Recurse']) { $chownParams += '-R' } if ($PSBoundParameters.ContainsKey('Group')) { $Owner = '{0}:{1}' -f $Owner,$Group } $chownParams = ($chownParams + @($Owner, $pathItem)) if ( $PSCmdlet.ShouldProcess("Performing the unix command 'chown $($chownParams -join ' ')'.", $PathItem, "chown $($chownParams -join ' ')") ) { if ($pathItem -eq '/' -and -not ($PSBoundParameters.ContainsKey('Force') -and $Force)) { # can't use the built-in --preserve-root because it's not available on Alpine linux Write-Warning "You are about to chown your root. Please use -Force." return } Write-Verbose -Message ('chown {0}' -f ($chownParams -join ' ')) Invoke-NativeCommand -Executable 'chown' -Parameters $chownParams -Verbose:$verbose | Foreach-Object -Process { Write-Error -Message $_ } } } } } #EndRegion './Public/FileSystem/Set-nxOwner.ps1' 120 #Region './Public/System/Get-nxDistributionInfo.ps1' 0 function Get-nxDistributionInfo { [CmdletBinding()] param ( [Parameter()] [System.String[]] $InfoFilePath = '/etc/*-release' ) $verbose = ($PSBoundParameters.ContainsKey('Verbose') -and $PSBoundParameters.Verbose) -or $VerbosePreference -ne 'SilentlyContinue' $InfoFilePath = [string[]](Get-Item $InfoFilePath -ErrorAction Stop -Verbose:$Verbose) Write-Verbose -Message "Extracting distro info from '$($InfoFilePath -join "', '")'" $properties = Get-Content -Path $InfoFilePath | Get-PropertyHashFromListOutput -Regex '^\s*(?<property>[\w-\s]*)=\s*"?(?<val>.*)\b' [PSCustomObject]$properties | Add-Member -TypeName 'nx.DistributionInfo' -PassThru } #EndRegion './Public/System/Get-nxDistributionInfo.ps1' 21 #Region './Public/System/Get-nxKernelInfo.ps1' 0 function Get-nxKernelInfo { [CmdletBinding()] param ( ) $verbose = ($PSBoundParameters.ContainsKey('Verbose') -and $PSBoundParameters.Verbose) -or $VerbosePreference -ne 'SilentlyContinue' $unameOutput = Invoke-NativeCommand -Executable 'uname' -Parameters @( # MacOS does not support long arguments '-s' # '--kernel-name', '-n' # '--nodename', '-r' # '--kernel-release', '-m' # '--machine', '-p' # '--processor', '-i' # '--hardware-platform', '-o' # '--operating-system' ) -Verbose:$verbose if ($unameOutput -match '^\/.*uname:\s+') { throw $unameOutput } $kernelName, $ComputerName, $kernelRelease, $machineHardware, $processor, $hardwarePlatform, $OS = $unameOutput -split '\s' # uname --kernel-version $kernelVersion = Invoke-NativeCommand -Executable 'uname' -Parameters '-v' -Verbose:$verbose [PSCustomObject]@{ kernelName = $kernelName ComputerName = $ComputerName KernelRelease = $kernelRelease KernelVersion = $kernelVersion MachineHardware = $machineHardware processor = $processor hardwarePlatform = $hardwarePlatform OS = $OS } | Add-Member -TypeName 'nx.KernelInfo' -PassThru } #EndRegion './Public/System/Get-nxKernelInfo.ps1' 43 #Region './Public/System/Get-nxLinuxStandardBaseRelease.ps1' 0 # By default on Debian 10, lsb-release package is not installed, so lsb_release # gives a command not found. function Get-nxLinuxStandardBaseRelease { [OutputType([PSCustomObject])] [CmdletBinding()] param ( ) $verbose = ($PSBoundParameters.ContainsKey('Verbose') -and $PSBoundParameters.Verbose) -or $VerbosePreference -ne 'SilentlyContinue' $properties = Invoke-NativeCommand -Executable 'lsb_release' -Parameters '--all' -Verbose:$Verbose | Get-PropertyHashFromListOutput -ErrorHandling { switch -Regex ($_) { '' { } 'No\sLSB\smodules' { Write-Verbose $_ } default { Write-Error "$_" } } } [PSCustomObject]$properties | Add-Member -TypeName 'nx.LsbRelease' -PassThru } Set-Alias -Name Get-LsbRelease -Value Get-nxLinuxStandardBaseRelease #EndRegion './Public/System/Get-nxLinuxStandardBaseRelease.ps1' 27 #Region './Public/usersAndGroups/Get-nxLocalGroup.ps1' 0 function Get-nxLocalGroup { [CmdletBinding(DefaultParameterSetName = 'byGroupName')] [OutputType()] param ( [Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'byGroupName', Position = 0)] [System.String[]] [Alias('Group')] $GroupName, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'byRegexPattern', Position = 0)] [regex] $Pattern ) begin { # by doing this, we prefer content accuracy than IO/Speed (the /etc/group may be read many times). $readEtcGroupCmd = { Get-Content -Path '/etc/group' | ForEach-Object -Process { [nxLocalGroup]$_ } } } process { if ($PSCmdlet.ParameterSetName -eq 'byGroupName' -and -not $PSBoundParameters.ContainsKey('GroupName')) { Write-Debug -Message "[Get-nxLocalGroup] Reading /etc/group without filter." &$readEtcGroupCmd } elseif ($PSCmdlet.ParameterSetName -eq 'byRegexPattern') { Write-Debug -Message "[Get-nxLocalGroup] Matching 'GroupName' with regex pattern '$Pattern'." &$readEtcGroupCmd | Where-Object -FilterScript { $_.GroupName -match $Pattern } } else { $allGroups = &$readEtcGroupCmd foreach ($GroupNameEntry in $GroupName) { Write-Debug -Message "[Get-nxLocalGroup] Finding Local group by GroupName '$GroupNameEntry'." $allGroups | Where-Object -FilterScript { $_.Groupname -eq $GroupNameEntry } } } } } #EndRegion './Public/usersAndGroups/Get-nxLocalGroup.ps1' 54 #Region './Public/usersAndGroups/Get-nxLocalUser.ps1' 0 function Get-nxLocalUser { [CmdletBinding(DefaultParameterSetName = 'byUserName')] [OutputType()] param ( [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'byUserName', Position = 0)] [System.String[]] [Alias('GroupMember')] $UserName, [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'byRegexPattern', Position = 0)] [regex] $Pattern ) begin { $readPasswdCmd = { Get-Content -Path '/etc/passwd' | ForEach-Object -Process { [nxLocalUser]$_ } } } process { if ($PSCmdlet.ParameterSetName -eq 'byUserName' -and -not $PSBoundParameters.ContainsKey('UserName')) { Write-Debug -Message "[Get-nxLocalUser] Reading /etc/passwd without filter." &$readPasswdCmd } elseif ($PSCmdlet.ParameterSetName -eq 'byRegexPattern') { Write-Debug -Message "[Get-nxLocalUser] Matching 'UserName' with regex pattern '$Pattern'." &$readPasswdCmd | Where-Object -FilterScript { $_.username -match $Pattern } } else { $allUsers = &$readPasswdCmd foreach ($userNameEntry in $UserName) { Write-Debug -Message "[Get-nxLocalUser] Finding Local users by UserName '$userNameEntry'." $allUsers | Where-Object -FilterScript { $_.username -eq $userNameEntry } } } } } #EndRegion './Public/usersAndGroups/Get-nxLocalUser.ps1' 53 #Region './Public/usersAndGroups/Get-nxLocalUserMemberOf.ps1' 0 function Get-nxLocalUserMemberOf { [CmdletBinding()] [OutputType([PSCustomObject[]])] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [System.String[]] [Alias('UserName','UserId')] $User ) process { foreach ($UserItem in $User) { [string] $UserName = '' if ($UserItem -match '^\d+$') { # by User ID $UserName = Get-nxLocalUser | Where-Object -FilterScript { $_.UserId -eq $UserItem } } else { # by User Name $UserName = $UserItem } $memberOf = (Invoke-NativeCommand -Executable 'id' -Parameters @('-G', '-n', $UserName)) -split '\s+' | Foreach-Object -Process { if ($_ -match '^id:\s') { throw $_ } else { Get-nxLocalGroup -GroupName $_ } } [PSCustomObject]@{ PsTypeName = 'nx.LocalUser.MemberOf' User = $UserName MemberOf = $memberOf } } } } #EndRegion './Public/usersAndGroups/Get-nxLocalUserMemberOf.ps1' 47 |