Dictionaries/Computer.Dict.Linux/Computer.Dict.Linux.psm1
<#
###### ####### ## ## ######## ## ## ######## ######## ######## ## ## ## ## ### ### ## ## ## ## ## ## ## ## ## ## ## #### #### ## ## ## ## ## ## ## ## ## ## ## ## ### ## ######## ## ## ## ###### ######## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ###### ####### ## ## ## ####### ## ######## ## ## #> # function Get-MyInvocation { # [CmdletBinding()] # [OutputType([String])] # Param ( # ) # Begin { # Write-EnterFunction # } # Process { # $MyInvocation # } # End { # Write-LeaveFunction # } # } <# .SYNOPSIS Get the computer name .DESCRIPTION .PARAMETER localhost request localhost's ComputerName .EXAMPLE $name = Get-ComputerName .NOTES This function comes from Dict.Unix module. #> function Get-ComputerName { [CmdletBinding()]Param ( ) Begin { Write-EnterFunction } Process { # delete everything after 1st dot to get only hostname (e.g. without domainname) return (hostname) -replace "\..*" } End { Write-LeaveFunction } } function Get-ComputerDomain { hostname -d } function Get-ComputerManufacturer { [CmdletBinding()][OutputType([String])]Param ( ) Begin { Write-EnterFunction } Process { return (New-HashtableFromCommand -Command "dmidecode | awk '/^System Information/,/^$/'" -sep ":" -SkipFirstLines 1).manufacturer } End { Write-LeaveFunction } } function Get-ComputerModel { [CmdletBinding()]Param ( ) Begin { Write-EnterFunction } Process { return (dmidecode | awk '/^System Information/,/^$/' | Select-Object -Skip 1 | ConvertFrom-StringData -Delimiter ":")."product name" # return (New-HashtableFromCommand -Command "dmidecode | awk '/^System Information/,/^$/'" -sep ":" -SkipFirstLines 1)."product name" } End { Write-LeaveFunction } } function Get-ComputerSerialNumber { [CmdletBinding()]Param ( ) Begin { Write-EnterFunction } Process { return (New-HashtableFromCommand -Command "dmidecode | awk '/^System Information/,/^$/'" -sep ":" -SkipFirstLines 1)."serial number" } End { Write-LeaveFunction } } <# .SYNOPSIS Know if computer was booted using old legacy BIOS mode or new UEFI. .DESCRIPTION To make next boot efficient, we need to know in what mode the computer booted to this stage. This function will tell us that. If every tests fail, or if we can't determined the boot mode, it defaults to "BIOS" mode. .EXAMPLE If (Get-ComputerFirmwareType -eq "UEFI") { # System is running UEFI firmware... } .EXAMPLE Switch (Get-ComputerFirmwareType) { "BIOS" { "Legacy BIOS" } "UEFI" { "UEFI" } Default { "Unknown" } } .OUTPUTS string "BIOS" or "UEFI" .NOTES General notes #> function Get-ComputerFirmwareType { [CmdletBinding()] [OutputType([String])] Param ( # [Parameter(Mandatory = $true, ValueFromPipeLine = $true)][string]$string ) Begin { Write-EnterFunction } Process { $bootMode = "BIOS" if (Test-DirExist "/sys/firmware/efi") { $bootMode = "UEFI" } return $bootMode } End { Write-LeaveFunction } } <# ######## ######## ## ## ######## ######## ## ## ######## ######## ## ## ## ## ## ## ## ### ## ## ## ## ## ## ## ## ## ## #### ## ## ## ###### ## ######### ###### ######## ## ## ## ###### ## ## ## ## ## ## ## ## ## #### ## ## ## ## ## ## ## ## ## ## ### ## ## ######## ## ## ## ######## ## ## ## ## ######## ## #> # Get-NetAdapter is not available on linux # array of interfaces found $Script:interfaces = $null <# .SYNOPSIS Gather informations about network interfaces from registry. .DESCRIPTION Get-NetAdapter is not available on linux. That's why we try to gather informations from the sysfs. Then we ask 'ip' for layer 3 data .EXAMPLE $interfaces = Get-ComputerNetAdapter .NOTES General notes #> function Get-ComputerNetAdapter { [CmdletBinding()] [OutputType([array])] Param ( # [Parameter(Mandatory = $true, ValueFromPipeLine = $true)][string]$string # [switch]$Passthru, # Force a refresh, do not blindly return cache [Alias('Refresh')] [switch]$Force ) Begin { Write-EnterFunction } Process { if (($null -eq $Script:interfaces) -or $Force) { $Script:interfaces = @() $Path = "/sys/class/net" foreach ($item in (Get-ChildItem $Path)) { $interface = @{} $interface.name = $item.name foreach ($subitem in (Get-ChildItem $item.fullname -File)) { $property = $subitem.name try { $interface.$property = (Get-Content $subitem -Raw) -replace "\n" } catch { Write-Warning "Unable to read $property property." } } # we are missing IP properties. # try with 'ip' command $output = Execute-Command -exe ip -args "-o -4 addr show dev $($item.name)" -PassThru # $regex = "\d: $($item.name)\s+inet (?<cidr>\d+\.\d+\.\d+\.\d+/\d+) brd (?<broadcast>\d+\.\d+\.\d+\.\d+) scope (?<scope>[a-z]+) (dynamic (?<dynamic>[a-z]*))? .*" # $regex = "\d: (?<ifname>[a-z0-9]+)\s+inet (?<cidr>\d+\.\d+\.\d+\.\d+/\d+)?(?<ipaddress>\d+\.\d+\.\d+\.\d+)? (brd (?<broadcast>\d+\.\d+\.\d+\.\d+))?(peer (?<peer>\d+\.\d+\.\d+\.\d+/\d+))? scope .*" $regex = "\d: $($item.name)\s+inet (?<cidr>\d+\.\d+\.\d+\.\d+/\d+)?(?<ipaddress>\d+\.\d+\.\d+\.\d+)? (brd (?<broadcast>\d+\.\d+\.\d+\.\d+))?(peer (?<peer>\d+\.\d+\.\d+\.\d+/\d+))? scope .*" if ($output -match $regex) { $interface.cidr = $Matches.cidr $interface.ipaddress = (($interface.cidr) -split "/")[0] $interface.broadcast = $Matches.broadcast $interface.scope = $Matches.scope $interface.dynamic = $Matches.dynamic } # Place here properties that we have to make common between all OS's $interface.macaddress = $interface.address $Script:interfaces += $interface } } return $Script:interfaces } End { Write-LeaveFunction } } <# ######## #### ###### ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ###### ##### ## ## ## ## ## ## ## ## ## ## ## ## ## ######## #### ###### ## ## #> <# .SYNOPSIS List local disks .DESCRIPTION Fetch all informations available about local disks. Linux lacks the 'Get-Disk' of the Storage module available on Windows. .EXAMPLE An example .NOTES General notes #> function Get-ComputerDisk { [CmdletBinding(DefaultParameterSetName = "ALL")] [OutputType([hashtable])] Param ( # Disk number [Parameter(Mandatory = $true, ParameterSetName = 'DISKNUMBER')][string]$DiskNumber, # Disk device name (without /dev) [Parameter(Mandatory = $true, ParameterSetName = 'DISKNAME')][string]$DiskName, # Full device address like in '/dev/sda' [Parameter(Mandatory = $true, ParameterSetName = 'DEVICE')][string]$Device, # Partition of the disk given its ID [Alias('UniqueId')] [Parameter(Mandatory = $true, ParameterSetName = 'DISKID')][string]$DiskId, # Return all $disks [Parameter(Mandatory = $false, ParameterSetName = 'ALL')][switch]$All ) Begin { Write-EnterFunction $disks = ((lsblk --output-all --json --tree) | convertfrom-json).blockdevices | Where-Object { $_.type -eq "disk" } # comply with windows code foreach ($d in $disks) { foreach ($part in $d.children) { # foreach <item> is created by reference, not by copy. So we can modify it # add IsActive to bootable partition if ($part.partflags -eq "0x80") { $part | Add-Member -Force -MemberType NoteProperty -Name IsActive -Value $true } else { $part | Add-Member -Force -MemberType NoteProperty -Name IsActive -Value $false } if ($part.Mountpoints) { $part | Add-Member -Force -MemberType NoteProperty -Name "AccessPaths" -Value $part.Mountpoints } if ($part.UUID) { $part | Add-Member -Force -MemberType NoteProperty -Name "Guid" -Value $part.UUID } $part | Add-Member -Force -MemberType NoteProperty -Name "FileSystemLabel" -Value $part.label } } } Process { switch ($PSCmdlet.ParameterSetName) { 'DISKNUMBER' { $disks = $disks[$DiskNumber] } 'DISKNAME' { $disks = $disks | Where-Object { $_.name -eq $DiskName } } 'DEVICE' { $disks = $disks | Where-Object { $_.path -eq $Device } } 'DISKID' { $disks = $disks | Where-Object { $_.ptuuid -eq $DiskId } } default { } } return $disks } End { Write-LeaveFunction } } <# .SYNOPSIS List local partitions .DESCRIPTION Fetch all informations available about local partitions. Linux lacks the 'Get-Partition' of the Storage module available on Windows. .EXAMPLE An example .NOTES General notes #> function Get-ComputerDiskPartition { [CmdletBinding(DefaultParameterSetName = "ALL")] [OutputType([hashtable])] Param ( # Partition object [Parameter(Mandatory = $true, ValueFromPipeLine = $true, ParameterSetName = 'OBJECT')]$InputObject, # Partition with UUID [Alias('UniqueId')] [Parameter(Mandatory = $true, ParameterSetName = 'PARTUUID')][string]$PartUUID, # Label of the partition to mount [Alias('Label', 'PartitionLabel')] [Parameter(Mandatory = $true, ParameterSetName = 'PARTLABEL')][string]$PartLabel, # Disk device name of the partition [Parameter(Mandatory = $true, ParameterSetName = 'DISKPART')][string]$Disk, # Partition number (can be several strings char since nvme disks. e.g. 'p1') [Alias('PartitionNumber')] [Parameter(Mandatory = $false, ParameterSetName = 'DISKPART')][string]$PartNum, # Full device address like in '/dev/sda1' [Parameter(Mandatory = $true, ParameterSetName = 'DEVICE')][string]$Device, # Mountpoint of a mounted partition [Alias('DriveLetter')] [Parameter(Mandatory = $true, ParameterSetName = 'MOUNTPOINT')][string]$Mountpoint, # Partition of the disk given its ID [Parameter(Mandatory = $true, ParameterSetName = 'DISKID')][string]$DiskId, # Return all partitions [Parameter(Mandatory = $false, ParameterSetName = 'ALL')][switch]$All ) Begin { Write-EnterFunction $disks = Get-ComputerDisk } Process { switch ($PSCmdlet.ParameterSetName) { 'OBJECT' { $partitions = ($disks.children | Where-Object { $_.partuuid -eq $InputObject.UUID }) } 'PARTUUID' { $partitions = ($disks.children | Where-Object { $_.partuuid -eq "$PartUUID" }) } 'PARTLABEL' { $partitions = ($disks.children | Where-Object { $_.label -eq "$PartLabel" }) } 'DISKPART' { $partitions = ($disks | Where-Object { $_.name -eq $Disk }).children if ($PartNumber) { $partitions = ($partitions | Where-Object { $_.name -eq "$Disk$PartNumber" }) } } 'DEVICE' { $partitions = ($disks.children | Where-Object { $_.path -like "$Device*" }) } 'MOUNTPOINT' { # $partitions = ($disks.children | Where-Object { $_.mountpoint -eq "$Mountpoint" }) $partitions = ($disks.children | Where-Object { $Mountpoint -in $_.Mountpoints }) } 'DISKID' { $partitions = ($disks.children | Where-Object { $_.ptuuid -eq "$DiskId" }) } default { $partitions = $disks.children } } return $partitions } End { Write-LeaveFunction } } <# .SYNOPSIS Mount a partition into running operating system .DESCRIPTION Mount specified partition .EXAMPLE An example .NOTES General notes .OUTPUTS [string] mountpoint #> function Mount-ComputerDiskPartition { [CmdletBinding()] [OutputType([String], [array])] Param ( # Partition object [Parameter(Mandatory = $true, ValueFromPipeLine = $true, ParameterSetName = 'OBJECT')]$InputObject, # UUID of the partition to mount [Parameter(Mandatory = $true, ParameterSetName = 'PARTUUID')][string]$PartUuid, # Label of the partition to mount [Alias('Label', 'PartitionLabel')] [Parameter(Mandatory = $true, ParameterSetName = 'PARTLABEL')][string]$PartLabel, # Disk device name of the partition [Parameter(Mandatory = $true, ParameterSetName = 'DISKPART')][string]$Disk, # Partition number (can be several strings char since nvme disks. e.g. 'p1') [Parameter(Mandatory = $true, ParameterSetName = 'DISKPART')][string]$PartNum, # Full device address like in '/dev/sda1' [Parameter(Mandatory = $true, ParameterSetName = 'DEVICE')][string]$Device, # options to pass [Parameter(Mandatory = $false)][string]$Options, # Recurse through partition children [Parameter(Mandatory = $false)][switch]$Recurse, # Specify mounting to this mountpoint [Parameter(Mandatory = $false)][string]$Mountpoint, # If partition is already mounted, it will mount it to another mountpoint [Parameter(Mandatory = $false)][switch]$Force, # if specified, return the whole partition object, # else return only mountpoint [switch]$Passthru ) Begin { Write-EnterFunction } Process { switch ($PSCmdlet.ParameterSetName) { 'OBJECT' { $partition = $InputObject } 'PARTUUID' { $partition = Get-ComputerDiskPartition -PartUUID $PartUuid } 'PARTLABEL' { $partition = Get-ComputerDiskPartition -PartLabel $PartLabel } 'DISKPART' { $partition = Get-ComputerDiskPartition -Disk $Disk -PartNum $PartNum } 'DEVICE' { $partition = Get-ComputerDiskPartition -Device $Device } } # handle -Bind first because if it already mounted we do not have to remount it twice if ($Force) { $Mountpoint = "/var/lib/pwsh.fw.computer/mountpoints/$($partition.Guid)" $partition = Mount-ComputerDiskPartition -InputObject $partition -Mountpoint $Mountpoint -Passthru } # partition is already mounted ? return mountpoint # 1st case -> $Mountpoint not specified and Partition already mounted -> return # 2nd case -> $Mountpoit specified and partition already mounted -> check if partition is mounted on this specific mountpoit if ((!$Mountpoint) -and $partition.mountpoint) { Write-Debug "Partition $($partition.name) already mounted at '$Mountpoint'" if ($Passthru) { return Get-ComputerDiskPartition -InputObject $partition } else { return $Mountpoint } } if ($Mountpoint -in $partition.mountpoints) { Write-Debug "Partition $($partition.name) already mounted at '$Mountpoint'" if ($Passthru) { return Get-ComputerDiskPartition -InputObject $partition } else { return $Mountpoint } } if ($partition.children) { if ($Recurse) { $Mountpoints = @() foreach ($c in $partition.children) { $Mountpoints += Mount-ComputerDiskPartition -InputObject $c -Recurse } if ($Passthru) { return Get-ComputerDiskPartition -InputObject $partition } else { return $Mountpoint } } else { Write-Warning "Partition $($partition.name) have children (subvolumes). You may want to mount those volumes instead." Write-Warning "Use -Recurse to mount subvolumes automatically." return $null } } if (!$Mountpoint) { # $Mountpoint = "/mnt/$($partition.name)" $Mountpoint = "/var/lib/pwsh.fw.computer/mountpoints/$($partition.Guid)" } $rc = New-Item $Mountpoint -ItemType Directory -Force Write-Debug "Mount partition $($partition.name) in $Mountpoint" # options is an array of comma separated values $aOptions = $Options -split "," switch ($partition.fstype) { 'ntfs' { # probe for mountability $rc = Execute-Command -exe ntfs-3g.probe -args "--readwrite $($partition.path)" -AsBool rc=$? switch (${rc}) { 14 { Write-Warning "Windows is hibernating, ntfs-3g will refuse to mount it." Write-Warning "We'll try to mount removing hiberfile" # if ${options} is defined, then OPTIONS="${options},ro" else, OPTIONS="ro" $aOptions += "remove_hiberfile" } } # Make sure the dirty flag is removed. If not, mounting the NTFS partition is impossible. $rc = Execute-Command -exe ntfsfix -args "-d $($partition.path)" # if ${options} is defined, then OPTIONS="-o ${options}" else, OPTIONS="" $rc = Execute-Command -exe ntfs-3g -rags "$($partition.path) $MountPoint $($aOptions -join ",")" } 'crypto_LUKS' { $passPhrase = Write-Question -Prompt "Please enter pass-phrase to decypher partition $($partition.name)" $rc = Execute-Command -exe "cryptsetup" -args "luksOpen $($partition.path) $($partition.name) - <<< ${passPhrase}" # if [ -e /dev/mapper/${part} ]; then # $mountPoint=$(MountPartition /dev/mapper/${part}) # return $(true) # else # CLog "ERR" "${FUNCNAME}(): failed to unlock luks partition /dev/${part}" # return $(false) # fi } 'swap' { # Do nothing, we do not mount swap. Write-Warning "Partition $($partition.name) is a SWAP partition. Skip it." } Default { # if partition already have a mountpoint, use another mount syntax if ($Force) { $rc = Execute-Command -exe mount -args "--bind $($partition.mountpoint) $MountPoint $($aOptions -join ",")" } else { $rc = Execute-Command -exe mount -args "-t auto $($partition.path) $MountPoint $($aOptions -join ",")" } } } if ($Passthru) { return Get-ComputerDiskPartition -InputObject $partition } else { return $Mountpoint } } End { Write-LeaveFunction } } |