mirror of
https://github.com/aphrody-labs/PowerShell.git
synced 2026-10-17 12:45:47 +00:00
Merge pull request #761 from PowerShell/andschwa/cli
Switch dotnet publish for dotnet build (and more)
This commit is contained in:
commit
b7a7d8f048
107 files changed
+17331
-372
No files matched your search
+6
-5
@@ -1,6 +1,3 @@
|
||||
[submodule "src/libpsl-native"]
|
||||
path = src/libpsl-native
|
||||
url = https://github.com/PowerShell/psl-native.git
|
||||
[submodule "src/omi"]
|
||||
path = src/omi
|
||||
url = https://github.com/Microsoft/omi.git
|
||||
@@ -11,8 +8,12 @@
|
||||
[submodule "src/windows-build"]
|
||||
path = src/windows-build
|
||||
url = https://github.com/PowerShell/psl-windows-build.git
|
||||
[submodule "src/Microsoft.PowerShell.Linux.Host/Modules/Pester"]
|
||||
path = src/Microsoft.PowerShell.Linux.Host/Modules/Pester
|
||||
[submodule "src/Modules/Pester"]
|
||||
path = src/Modules/Pester
|
||||
url = https://github.com/PowerShell/psl-pester.git
|
||||
branch = develop
|
||||
ignore = dirty
|
||||
[submodule "src/libpsl-native/test/googletest"]
|
||||
path = src/libpsl-native/test/googletest
|
||||
url = https://github.com/google/googletest.git
|
||||
ignore = dirty
|
||||
+4
-13
@@ -1,25 +1,16 @@
|
||||
language: cpp
|
||||
sudo: required
|
||||
dist: trusty
|
||||
cache:
|
||||
apt: true
|
||||
directories:
|
||||
- $HOME/.nuget
|
||||
git:
|
||||
submodules: false
|
||||
before_install:
|
||||
- git config --global url.git@github.com:.insteadOf https://github.com/
|
||||
- git submodule update --init --recursive -- src/libpsl-native src/windows-build src/Microsoft.PowerShell.Linux.Host/Modules/Pester
|
||||
- sudo sh -c 'echo "deb [arch=amd64] http://apt-mo.trafficmanager.net/repos/dotnet/ trusty main" > /etc/apt/sources.list.d/dotnetdev.list'
|
||||
- sudo apt-key adv --keyserver apt-mo.trafficmanager.net --recv-keys 417A0893
|
||||
- sudo apt-get -qq update
|
||||
- sudo apt-get install -y dotnet=1.0.0.001675-1
|
||||
- git submodule update --init -- src/windows-build src/Modules/Pester src/libpsl-native/test/googletest
|
||||
- ./bootstrap.sh
|
||||
- ./download.sh
|
||||
- sudo dpkg -i powershell.deb
|
||||
- sudo dpkg -i ./powershell.deb
|
||||
script:
|
||||
- powershell -c "Import-Module ./PowerShellGitHubDev.psm1; Start-PSBuild"
|
||||
- ./pester.sh
|
||||
- ./xunit.sh
|
||||
- powershell -c "Import-Module ./PowerShellGitHubDev.psm1; Start-PSBuild; Start-PSxUnit; Start-PSPester"
|
||||
notifications:
|
||||
slack:
|
||||
secure: sKYd4n61+ZFzGZuWGUl8V1kN0NM16wRVOFVlNhlFCwnkrEsKROb++EvXf5uwnKuzxkhEjvPWO+UFgeshQDoR93y4s5YLfhC5JupK4nUzjPzWs208KTrh8u/x9MY8X6Ojxi85EEAiku5GzMoMlkucSStZUYwbIfnelzqdw8uoRwmm2MW4XCPwsuEuDUVghyiva0Mdx1G6MopCrK8T96WywJXT3chhfZQgVt+sQCBt9g+2kjDaObKrzG0P07IVK43ZpDgnu6AoxlyBzIx9mJH2Oa/tki3/kTO72Wcp3ps3qvmiStADamzVKR9p1VlWCLWAd6VOehxuByCGEyujpzk135Wud2DZYO+8LD6inZVhFe3Wt5pCU9BDXZppiATfMCqgXEH7nK54pEn79yHcjthRJ2+Z9ot7As2fu3RSBmTAi8nRP0fxRyX/jctR3S6P0qt0y1ynx9nzBfhmhPQW0PMVazWS/nruQIvK/3iiYXjZxM5bBwIvabmwV00EYeTdbL6ufXWNgQcG1ZWkDsi2I3vst/ytUbHwaFYg83bXWpxg9DCzJeWLVUvE5/3NfBxRAuCTot/fgTEA9IYScvrlL7Q/bT0cOt0vEM98MPf1UO+WP85uxhsRgHtwDEo+jMaL6ZFkPhlV6mmmED4NdY2//a571cLNXdnuMAze5O3TWGBG53g=
|
||||
+260
-252
@@ -17,19 +17,19 @@ try {
|
||||
$IsWindows = $true
|
||||
}
|
||||
|
||||
function Start-PSBuild
|
||||
{
|
||||
|
||||
function Start-PSBuild {
|
||||
[CmdletBinding(DefaultParameterSetName='CoreCLR')]
|
||||
param(
|
||||
[switch]$Restore,
|
||||
[switch]$Clean,
|
||||
[string]$Output,
|
||||
|
||||
# These runtimes must match those in project.json
|
||||
# We do not use ValidateScript since we want tab completion
|
||||
[ValidateSet("ubuntu.14.04-x64",
|
||||
"centos.7.1-x64",
|
||||
"win7-x64",
|
||||
"win81-x64",
|
||||
"win10-x64",
|
||||
"osx.10.10-x64",
|
||||
"osx.10.11-x64")]
|
||||
@@ -44,185 +44,213 @@ function Start-PSBuild
|
||||
|
||||
[Parameter(ParameterSetName='FullCLR')]
|
||||
[ValidateSet("Debug",
|
||||
"Release")]
|
||||
[string]$msbuildConfiguration = "Release"
|
||||
"Release")]
|
||||
[string]$msbuildConfiguration = "Release"
|
||||
)
|
||||
|
||||
function precheck([string]$command, [string]$missedMessage)
|
||||
{
|
||||
$c = Get-Command $command -ErrorAction SilentlyContinue
|
||||
if (-not $c)
|
||||
{
|
||||
Write-Warning $missedMessage
|
||||
return $false
|
||||
}
|
||||
else
|
||||
{
|
||||
return $true
|
||||
}
|
||||
}
|
||||
|
||||
function log([string]$message)
|
||||
{
|
||||
Write-Host -Foreground Green $message
|
||||
}
|
||||
|
||||
# simplify ParameterSetNames, set output
|
||||
if ($PSCmdlet.ParameterSetName -eq 'FullCLR')
|
||||
{
|
||||
# simplify ParameterSetNames
|
||||
if ($PSCmdlet.ParameterSetName -eq 'FullCLR') {
|
||||
$FullCLR = $true
|
||||
}
|
||||
|
||||
if (-not $Output)
|
||||
{
|
||||
if ($FullCLR) { $Output = "$PSScriptRoot/binFull" } else { $Output = "$PSScriptRoot/bin" }
|
||||
}
|
||||
|
||||
# verify we have all tools in place to do the build
|
||||
$precheck = precheck 'dotnet' "Build dependency 'dotnet' not found in PATH! See: https://dotnet.github.io/getting-started/"
|
||||
if ($FullCLR)
|
||||
{
|
||||
if ($FullCLR) {
|
||||
# cmake is needed to build powershell.exe
|
||||
$precheck = $precheck -and (precheck 'cmake' 'cmake not found. You can install it from https://chocolatey.org/packages/cmake.portable')
|
||||
|
||||
|
||||
# msbuild is needed to build powershell.exe
|
||||
# msbuild is part of .NET Framework, we can try to get it from well-known location.
|
||||
if (-not (Get-Command -Name msbuild -ErrorAction Ignore))
|
||||
{
|
||||
if (-not (Get-Command -Name msbuild -ErrorAction Ignore)) {
|
||||
$env:path += ";${env:SystemRoot}\Microsoft.Net\Framework\v4.0.30319"
|
||||
}
|
||||
|
||||
$precheck = $precheck -and (precheck 'msbuild' 'msbuild not found. Install Visual Studio 2015.')
|
||||
}
|
||||
|
||||
if (-not $precheck) { return }
|
||||
} elseif ($IsLinux -Or $IsOSX) {
|
||||
$InstallCommand = if ($IsLinux) {
|
||||
'apt-get'
|
||||
} elseif ($IsOSX) {
|
||||
'brew'
|
||||
}
|
||||
|
||||
# handle clean
|
||||
if ($Clean) {
|
||||
Remove-Item -Force -Recurse $Output -ErrorAction SilentlyContinue
|
||||
foreach ($Dependency in 'cmake', 'make', 'g++') {
|
||||
$precheck = $precheck -and (precheck $Dependency "Build dependency '$Dependency' not found. Run '$InstallCommand install $Dependency'")
|
||||
}
|
||||
}
|
||||
|
||||
New-Item -Force -Type Directory $Output | Out-Null
|
||||
if (-Not $Runtime) {
|
||||
$Runtime = dotnet --info | % {
|
||||
if ($_ -match "RID") {
|
||||
$_ -split "\s+" | Select-Object -Last 1
|
||||
}
|
||||
}
|
||||
|
||||
if (-Not $Runtime) {
|
||||
Write-Warning "Could not determine Runtime Identifier, please update dotnet"
|
||||
$precheck = $false
|
||||
} else {
|
||||
log "Runtime not specified, using $Runtime"
|
||||
}
|
||||
}
|
||||
|
||||
# Abort if any precheck failed
|
||||
if (-not $precheck) {
|
||||
return
|
||||
}
|
||||
|
||||
# define key build variables
|
||||
if ($FullCLR)
|
||||
{
|
||||
if ($FullCLR) {
|
||||
$Top = "$PSScriptRoot\src\Microsoft.PowerShell.ConsoleHost"
|
||||
$framework = 'net451'
|
||||
$Framework = 'net451'
|
||||
} else {
|
||||
$Top = "$PSScriptRoot/src/Microsoft.PowerShell.Host"
|
||||
$Framework = 'netstandardapp1.5'
|
||||
}
|
||||
else
|
||||
{
|
||||
$Top = "$PSScriptRoot/src/Microsoft.PowerShell.Linux.Host"
|
||||
$framework = 'netstandardapp1.5'
|
||||
|
||||
if ($IsLinux -Or $IsOSX) {
|
||||
$Configuration = "Linux"
|
||||
$Executable = "powershell"
|
||||
} else {
|
||||
$Configuration = "Debug"
|
||||
$Executable = "powershell.exe"
|
||||
}
|
||||
|
||||
$Arguments = @()
|
||||
$Arguments += "--framework", $Framework
|
||||
$Arguments += "--configuration", $Configuration
|
||||
$Arguments += "--runtime", $Runtime
|
||||
|
||||
# FullCLR only builds a library, so there is no runtime component
|
||||
if ($FullCLR) {
|
||||
$script:Output = [IO.Path]::Combine($Top, "bin", $Configuration, $Framework, $Executable)
|
||||
} else {
|
||||
$script:Output = [IO.Path]::Combine($Top, "bin", $Configuration, $Framework, $Runtime, $Executable)
|
||||
}
|
||||
Write-Verbose "script:Output is $script:Output"
|
||||
|
||||
# handle Restore
|
||||
if ($Restore -Or -Not (Test-Path "$Top/project.lock.json")) {
|
||||
log "Run dotnet restore"
|
||||
|
||||
$Arguments = @("--verbosity")
|
||||
$RestoreArguments = @("--verbosity")
|
||||
if ($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent) {
|
||||
$Arguments += "Info" } else { $Arguments += "Warning" }
|
||||
$RestoreArguments += "Info"
|
||||
} else {
|
||||
$RestoreArguments += "Warning"
|
||||
}
|
||||
|
||||
if ($Runtime) { $Arguments += "--runtime", $Runtime }
|
||||
$RestoreArguments += "$PSScriptRoot"
|
||||
|
||||
$Arguments += "$PSScriptRoot"
|
||||
|
||||
dotnet restore $Arguments
|
||||
dotnet restore $RestoreArguments
|
||||
}
|
||||
|
||||
# Build native components
|
||||
if (-not $FullCLR)
|
||||
{
|
||||
if ($IsLinux -Or $IsOSX) {
|
||||
log "Start building native components"
|
||||
$InstallCommand = if ($IsLinux) { "apt-get" } elseif ($IsOSX) { "brew" }
|
||||
foreach ($Dependency in "cmake", "g++") {
|
||||
if (-Not (Get-Command $Dependency -ErrorAction SilentlyContinue)) {
|
||||
throw "Build dependency '$Dependency' not found in PATH! Run '$InstallCommand install $Dependency'"
|
||||
}
|
||||
}
|
||||
|
||||
$Ext = if ($IsLinux) { "so" } elseif ($IsOSX) { "dylib" }
|
||||
$Native = "$PSScriptRoot/src/libpsl-native"
|
||||
$Lib = "$Top/libpsl-native.$Ext"
|
||||
Write-Verbose "Building $Lib"
|
||||
|
||||
try {
|
||||
Push-Location $Native
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug .
|
||||
make -j
|
||||
make test
|
||||
} finally {
|
||||
Pop-Location
|
||||
}
|
||||
|
||||
if (-Not (Test-Path $Lib)) { throw "Compilation of $Lib failed" }
|
||||
if ($IsLinux -Or $IsOSX) {
|
||||
$Ext = if ($IsLinux) {
|
||||
"so"
|
||||
} elseif ($IsOSX) {
|
||||
"dylib"
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
$Native = "$PSScriptRoot/src/libpsl-native"
|
||||
$Lib = "$Top/libpsl-native.$Ext"
|
||||
log "Start building $Lib"
|
||||
|
||||
try {
|
||||
Push-Location $Native
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug .
|
||||
make -j
|
||||
make test
|
||||
} finally {
|
||||
Pop-Location
|
||||
}
|
||||
|
||||
if (-Not (Test-Path $Lib)) {
|
||||
throw "Compilation of $Lib failed"
|
||||
}
|
||||
} elseif ($FullCLR) {
|
||||
log "Start building native powershell.exe"
|
||||
$build = "$PSScriptRoot/build"
|
||||
if ($Clean) {
|
||||
Remove-Item -Force -Recurse $build -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
mkdir $build -ErrorAction SilentlyContinue
|
||||
try
|
||||
{
|
||||
Push-Location $build
|
||||
try {
|
||||
Push-Location .\src\powershell-native
|
||||
|
||||
if ($cmakeGenerator)
|
||||
{
|
||||
cmake -G $cmakeGenerator ..\src\powershell-native
|
||||
}
|
||||
else
|
||||
{
|
||||
cmake ..\src\powershell-native
|
||||
if ($cmakeGenerator) {
|
||||
cmake -G $cmakeGenerator .
|
||||
} else {
|
||||
cmake .
|
||||
}
|
||||
|
||||
msbuild powershell.vcxproj /p:Configuration=$msbuildConfiguration
|
||||
cp -rec $msbuildConfiguration\* $Output
|
||||
|
||||
} finally {
|
||||
Pop-Location
|
||||
}
|
||||
finally { Pop-Location }
|
||||
}
|
||||
|
||||
log "Building PowerShell"
|
||||
$Arguments = "--framework", $framework, "--output", $Output
|
||||
if ($IsLinux -Or $IsOSX) { $Arguments += "--configuration", "Linux" }
|
||||
if ($Runtime) { $Arguments += "--runtime", $Runtime }
|
||||
|
||||
if ($FullCLR)
|
||||
{
|
||||
# there is a problem with code signing:
|
||||
# AssemblyKeyFileAttribute file path cannot be correctly located, if `dotnet publish $TOP` syntax is used
|
||||
# we workaround it with calling `dotnet publish` from $TOP directory instead.
|
||||
try {
|
||||
# Relative paths do not work well if cwd is not changed to project
|
||||
log "Run `dotnet build $Arguments` from $pwd"
|
||||
Push-Location $Top
|
||||
}
|
||||
else
|
||||
{
|
||||
$Arguments += $Top
|
||||
dotnet build $Arguments
|
||||
log "PowerShell output: $script:Output"
|
||||
} finally {
|
||||
Pop-Location
|
||||
}
|
||||
|
||||
Write-Verbose "Run dotnet publish $Arguments from $pwd"
|
||||
}
|
||||
|
||||
# this try-finally is part of workaround about AssemblyKeyFileAttribute issue
|
||||
try
|
||||
{
|
||||
dotnet publish $Arguments
|
||||
|
||||
function Get-PSOutput {
|
||||
[CmdletBinding()]param()
|
||||
if (-Not $Output) {
|
||||
throw '$script:Output is not defined, run Start-PSBuild'
|
||||
}
|
||||
finally
|
||||
{
|
||||
if ($FullCLR) { Pop-Location }
|
||||
|
||||
$Output
|
||||
}
|
||||
|
||||
|
||||
function Start-PSPester {
|
||||
[CmdletBinding()]param(
|
||||
[string]$Flags = '-EnableExit -OutputFile pester-tests.xml -OutputFormat NUnitXml',
|
||||
[string]$Tests = "*",
|
||||
[ValidateScript({ Test-Path -PathType Container $_})]
|
||||
[string]$Directory = "$PSScriptRoot/test/powershell"
|
||||
)
|
||||
|
||||
& (Get-PSOutput) -c "Invoke-Pester $Flags $Directory/$Tests"
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "$LASTEXITCODE Pester tests failed"
|
||||
}
|
||||
}
|
||||
|
||||
function Start-PSPackage
|
||||
{
|
||||
|
||||
function Start-PSxUnit {
|
||||
[CmdletBinding()]param()
|
||||
if ($IsWindows) {
|
||||
throw "xUnit tests are only currently supported on Linux / OS X"
|
||||
}
|
||||
|
||||
$Content = Split-Path -Parent (Get-PSOutput)
|
||||
$Arguments = "--configuration", "Linux"
|
||||
try {
|
||||
Push-Location $PSScriptRoot/test/csharp
|
||||
dotnet build $Arguments
|
||||
Copy-Item -ErrorAction SilentlyContinue -Recurse -Path $Content/* -Include Modules,libpsl-native* -Destination "./bin/Linux/netstandardapp1.5/ubuntu.14.04-x64"
|
||||
dotnet test $Arguments
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "$LASTEXITCODE xUnit tests failed"
|
||||
}
|
||||
} finally {
|
||||
Pop-Location
|
||||
}
|
||||
}
|
||||
|
||||
function Start-PSPackage {
|
||||
# PowerShell packages use Semantic Versioning http://semver.org/
|
||||
#
|
||||
# Ubuntu and OS X packages are supported.
|
||||
param(
|
||||
[CmdletBinding()]param(
|
||||
[string]$Version,
|
||||
[int]$Iteration = 1,
|
||||
[ValidateSet("deb", "osxpkg", "rpm")]
|
||||
@@ -285,8 +313,8 @@ function Start-PSPackage
|
||||
"$PSScriptRoot/package/powershell=/usr/local/bin"
|
||||
}
|
||||
|
||||
function Start-DevPSGitHub
|
||||
{
|
||||
|
||||
function Start-DevPSGitHub {
|
||||
param(
|
||||
[switch]$ZapDisable,
|
||||
[string[]]$ArgumentList = '',
|
||||
@@ -295,27 +323,23 @@ function Start-DevPSGitHub
|
||||
[switch]$NoNewWindow
|
||||
)
|
||||
|
||||
try
|
||||
{
|
||||
if ($LoadProfile -eq $false)
|
||||
{
|
||||
try {
|
||||
if ($LoadProfile -eq $false) {
|
||||
$ArgumentList = @('-noprofile') + $ArgumentList
|
||||
}
|
||||
|
||||
$env:DEVPATH = $binDir
|
||||
if ($ZapDisable)
|
||||
{
|
||||
if ($ZapDisable) {
|
||||
$env:COMPLUS_ZapDisable = 1
|
||||
}
|
||||
|
||||
if (-Not (Test-Path $binDir\powershell.exe.config))
|
||||
{
|
||||
if (-Not (Test-Path $binDir\powershell.exe.config)) {
|
||||
$configContents = @"
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<runtime>
|
||||
<developmentMode developerInstallation="true"/>
|
||||
</runtime>
|
||||
<runtime>
|
||||
<developmentMode developerInstallation="true"/>
|
||||
</runtime>
|
||||
</configuration>
|
||||
"@
|
||||
$configContents | Out-File -Encoding Ascii $binDir\powershell.exe.config
|
||||
@@ -333,71 +357,29 @@ function Start-DevPSGitHub
|
||||
}
|
||||
|
||||
Start-Process @startProcessArgs
|
||||
}
|
||||
finally
|
||||
{
|
||||
} finally {
|
||||
ri env:DEVPATH
|
||||
if ($ZapDisable)
|
||||
{
|
||||
if ($ZapDisable) {
|
||||
ri env:COMPLUS_ZapDisable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
## this function is from Dave Wyatt's answer on
|
||||
## http://stackoverflow.com/questions/22002748/hashtables-from-convertfrom-json-have-different-type-from-powershells-built-in-h
|
||||
function Convert-PSObjectToHashtable
|
||||
{
|
||||
param (
|
||||
[Parameter(ValueFromPipeline)]
|
||||
$InputObject
|
||||
)
|
||||
|
||||
process
|
||||
{
|
||||
if ($null -eq $InputObject) { return $null }
|
||||
|
||||
if ($InputObject -is [System.Collections.IEnumerable] -and $InputObject -isnot [string])
|
||||
{
|
||||
$collection = @(
|
||||
foreach ($object in $InputObject) { Convert-PSObjectToHashtable $object }
|
||||
)
|
||||
|
||||
Write-Output -NoEnumerate $collection
|
||||
}
|
||||
elseif ($InputObject -is [psobject])
|
||||
{
|
||||
$hash = @{}
|
||||
|
||||
foreach ($property in $InputObject.PSObject.Properties)
|
||||
{
|
||||
$hash[$property.Name] = Convert-PSObjectToHashtable $property.Value
|
||||
}
|
||||
|
||||
$hash
|
||||
}
|
||||
else
|
||||
{
|
||||
$InputObject
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.EXAMPLE Copy-SubmoduleFiles # copy files FROM submodule TO src/<project> folders
|
||||
.EXAMPLE Copy-SubmoduleFiles -ToSubmodule # copy files FROM src/<project> folders TO submodule
|
||||
#>
|
||||
function Copy-SubmoduleFiles {
|
||||
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[string]$mappingFilePath = "$PSScriptRoot/mapping.json",
|
||||
[switch]$ToSubmodule
|
||||
)
|
||||
|
||||
|
||||
if (-not (Test-Path $mappingFilePath))
|
||||
{
|
||||
|
||||
if (-not (Test-Path $mappingFilePath)) {
|
||||
throw "Mapping file not found in $mappingFilePath"
|
||||
}
|
||||
|
||||
@@ -405,47 +387,38 @@ function Copy-SubmoduleFiles {
|
||||
|
||||
# mapping.json assumes the root folder
|
||||
Push-Location $PSScriptRoot
|
||||
try
|
||||
{
|
||||
try {
|
||||
$m.GetEnumerator() | % {
|
||||
|
||||
if ($ToSubmodule)
|
||||
{
|
||||
if ($ToSubmodule) {
|
||||
cp $_.Value $_.Key -Verbose:$Verbose
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
mkdir (Split-Path $_.Value) -ErrorAction SilentlyContinue > $null
|
||||
cp $_.Key $_.Value -Verbose:$Verbose
|
||||
cp $_.Key $_.Value -Verbose:$Verbose
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
} finally {
|
||||
Pop-Location
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
<#
|
||||
.EXAMPLE Create-MappingFile # create mapping.json in the root folder from project.json files
|
||||
.EXAMPLE Create-MappingFile # create mapping.json in the root folder from project.json files
|
||||
#>
|
||||
function New-MappingFile
|
||||
{
|
||||
function New-MappingFile {
|
||||
param(
|
||||
[string]$mappingFilePath = "$PSScriptRoot/mapping.json",
|
||||
[switch]$IgnoreCompileFiles,
|
||||
[switch]$Ignoreresource
|
||||
)
|
||||
|
||||
function Get-MappingPath([string]$project, [string]$path)
|
||||
{
|
||||
if ($project -match 'TypeCatalogGen')
|
||||
{
|
||||
function Get-MappingPath([string]$project, [string]$path) {
|
||||
if ($project -match 'TypeCatalogGen') {
|
||||
return Split-Path $path -Leaf
|
||||
}
|
||||
|
||||
if ($project -match 'Microsoft.Management.Infrastructure')
|
||||
{
|
||||
|
||||
if ($project -match 'Microsoft.Management.Infrastructure') {
|
||||
return Split-Path $path -Leaf
|
||||
}
|
||||
|
||||
@@ -456,8 +429,7 @@ function New-MappingFile
|
||||
|
||||
# assumes the root folder
|
||||
Push-Location $PSScriptRoot
|
||||
try
|
||||
{
|
||||
try {
|
||||
$projects = ls .\src\ -Recurse -Depth 2 -Filter 'project.json'
|
||||
$projects | % {
|
||||
$project = Split-Path $_.FullName
|
||||
@@ -465,8 +437,7 @@ function New-MappingFile
|
||||
if (-not $IgnoreCompileFiles) {
|
||||
$json.compileFiles | % {
|
||||
if ($_) {
|
||||
if (-not $_.EndsWith('AssemblyInfo.cs'))
|
||||
{
|
||||
if (-not $_.EndsWith('AssemblyInfo.cs')) {
|
||||
$fullPath = Join-Path $project (Get-MappingPath -project $project -path $_)
|
||||
$mapping[$_.Replace('../', 'src/')] = ($fullPath.Replace("$($pwd.Path)\",'')).Replace('\', '/')
|
||||
}
|
||||
@@ -485,38 +456,19 @@ function New-MappingFile
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
} finally {
|
||||
Pop-Location
|
||||
}
|
||||
|
||||
Set-Content -Value ($mapping | ConvertTo-Json) -Path $mappingFilePath -Encoding Ascii
|
||||
}
|
||||
|
||||
function Get-InvertedOrderedMap
|
||||
{
|
||||
param(
|
||||
$h
|
||||
)
|
||||
$res = [ordered]@{}
|
||||
foreach ($q in $h.GetEnumerator()) {
|
||||
if ($res.Contains($q.Value))
|
||||
{
|
||||
throw "Cannot invert hashtable: duplicated key $($q.Value)"
|
||||
}
|
||||
|
||||
$res[$q.Value] = $q.Key
|
||||
}
|
||||
return $res
|
||||
}
|
||||
|
||||
<#
|
||||
.EXAMPLE Send-GitDiffToSd -diffArg1 45555786714d656bd31cbce67dbccb89c433b9cb -diffArg2 45555786714d656bd31cbce67dbccb89c433b9cb~1 -pathToAdmin d:\e\ps_dev\admin
|
||||
.EXAMPLE Send-GitDiffToSd -diffArg1 45555786714d656bd31cbce67dbccb89c433b9cb -diffArg2 45555786714d656bd31cbce67dbccb89c433b9cb~1 -pathToAdmin d:\e\ps_dev\admin
|
||||
Apply a signle commit to admin folder
|
||||
#>
|
||||
function Send-GitDiffToSd
|
||||
{
|
||||
function Send-GitDiffToSd {
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[string]$diffArg1,
|
||||
@@ -533,32 +485,88 @@ function Send-GitDiffToSd
|
||||
$affectedFiles = git diff --name-only $diffArg1 $diffArg2
|
||||
$rev = Get-InvertedOrderedMap $m
|
||||
foreach ($file in $affectedFiles) {
|
||||
if ($rev.Contains)
|
||||
{
|
||||
if ($rev.Contains) {
|
||||
$sdFilePath = Join-Path $pathToAdmin $rev[$file].Substring('src/monad/'.Length)
|
||||
$diff = git diff $diffArg1 $diffArg2 -- $file
|
||||
if ($diff)
|
||||
{
|
||||
if ($diff) {
|
||||
Write-Host -Foreground Green "Apply patch to $sdFilePath"
|
||||
Set-Content -Value $diff -Path $env:TEMP\diff -Encoding Ascii
|
||||
if ($WhatIf)
|
||||
{
|
||||
if ($WhatIf) {
|
||||
Write-Host -Foreground Green "Patch content"
|
||||
cat $env:TEMP\diff
|
||||
} else {
|
||||
& $patchPath --binary -p1 $sdFilePath $env:TEMP\diff
|
||||
}
|
||||
else
|
||||
{
|
||||
& $patchPath --binary -p1 $sdFilePath $env:TEMP\diff
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
Write-Host -Foreground Green "No changes in $file"
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
Write-Host -Foreground Green "Ignore changes in $file, because there is no mapping for it"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function script:log([string]$message) {
|
||||
Write-Host -Foreground Green $message
|
||||
}
|
||||
|
||||
|
||||
function script:precheck([string]$command, [string]$missedMessage) {
|
||||
$c = Get-Command $command -ErrorAction SilentlyContinue
|
||||
if (-not $c) {
|
||||
Write-Warning $missedMessage
|
||||
return $false
|
||||
} else {
|
||||
return $true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function script:Get-InvertedOrderedMap {
|
||||
param(
|
||||
$h
|
||||
)
|
||||
$res = [ordered]@{}
|
||||
foreach ($q in $h.GetEnumerator()) {
|
||||
if ($res.Contains($q.Value)) {
|
||||
throw "Cannot invert hashtable: duplicated key $($q.Value)"
|
||||
}
|
||||
|
||||
$res[$q.Value] = $q.Key
|
||||
}
|
||||
return $res
|
||||
}
|
||||
|
||||
|
||||
## this function is from Dave Wyatt's answer on
|
||||
## http://stackoverflow.com/questions/22002748/hashtables-from-convertfrom-json-have-different-type-from-powershells-built-in-h
|
||||
function script:Convert-PSObjectToHashtable {
|
||||
param (
|
||||
[Parameter(ValueFromPipeline)]
|
||||
$InputObject
|
||||
)
|
||||
|
||||
process {
|
||||
if ($null -eq $InputObject) { return $null }
|
||||
|
||||
if ($InputObject -is [System.Collections.IEnumerable] -and $InputObject -isnot [string]) {
|
||||
$collection = @(
|
||||
foreach ($object in $InputObject) { Convert-PSObjectToHashtable $object }
|
||||
)
|
||||
|
||||
Write-Output -NoEnumerate $collection
|
||||
} elseif ($InputObject -is [psobject]) {
|
||||
$hash = @{}
|
||||
|
||||
foreach ($property in $InputObject.PSObject.Properties)
|
||||
{
|
||||
$hash[$property.Name] = Convert-PSObjectToHashtable $property.Value
|
||||
}
|
||||
|
||||
$hash
|
||||
} else {
|
||||
$InputObject
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
-9
@@ -6,9 +6,6 @@ environment:
|
||||
priv_key:
|
||||
secure: <encryped-value>
|
||||
|
||||
cache:
|
||||
- '%LocalAppData%\Microsoft\dotnet'
|
||||
|
||||
notifications:
|
||||
- provider: Slack
|
||||
incoming_webhook:
|
||||
@@ -20,9 +17,9 @@ install:
|
||||
- ps: $fileContent += "`n-----END RSA PRIVATE KEY-----`n"
|
||||
- ps: Set-Content c:\users\appveyor\.ssh\id_rsa $fileContent
|
||||
- git config --global url.git@github.com:.insteadOf https://github.com/
|
||||
- git submodule update --init --recursive -- src/windows-build src/Microsoft.PowerShell.Linux.Host/Modules/Pester
|
||||
- git submodule update --init -- src/windows-build src/Modules/Pester
|
||||
- ps: Invoke-WebRequest -Uri https://raw.githubusercontent.com/dotnet/cli/rel/1.0.0/scripts/obtain/install.ps1 -OutFile install.ps1
|
||||
- ps: ./install.ps1 -version 1.0.0.001888
|
||||
- ps: ./install.ps1 -version 1.0.0-beta-002198
|
||||
|
||||
build_script:
|
||||
- ps: |
|
||||
@@ -38,15 +35,17 @@ test_script:
|
||||
$ErrorActionPreference = 'Stop'
|
||||
#
|
||||
# CoreCLR
|
||||
$env:CoreOutput = "$pwd\src\Microsoft.PowerShell.Host\bin\Debug\netstandardapp1.5\win81-x64"
|
||||
Write-Host -Foreground Green 'Run CoreCLR tests'
|
||||
$testResultsFile = "$pwd\TestsResults.xml"
|
||||
.\bin\powershell.exe --noprofile -c "Import-Module .\bin\Modules\Microsoft.PowerShell.Platform; Invoke-Pester test/powershell -OutputFormat NUnitXml -OutputFile $testResultsFile"
|
||||
& ("$env:CoreOutput\powershell.exe") -c "Invoke-Pester test/powershell -OutputFormat NUnitXml -OutputFile $testResultsFile"
|
||||
(New-Object 'System.Net.WebClient').UploadFile("https://ci.appveyor.com/api/testresults/nunit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path $testResultsFile))
|
||||
#
|
||||
# FullCLR
|
||||
$env:FullOutput = "$pwd\src\Microsoft.PowerShell.ConsoleHost\bin\Debug\net451"
|
||||
Write-Host -Foreground Green 'Run FullCLR tests'
|
||||
$testResultsFileFullCLR = "$pwd\TestsResults.FullCLR.xml"
|
||||
Start-DevPSGitHub -binDir $pwd\binFull -NoNewWindow -ArgumentList '-command', "Import-Module .\src\Microsoft.PowerShell.Linux.Host\Modules\Pester; Import-Module .\bin\Modules\Microsoft.PowerShell.Platform; Invoke-Pester test/fullCLR -OutputFormat NUnitXml -OutputFile $testResultsFileFullCLR"
|
||||
Start-DevPSGitHub -binDir $env:FullOutput -NoNewWindow -ArgumentList '-command', "Import-Module .\src\Modules\Pester; Import-Module .\bin\Modules\Microsoft.PowerShell.Platform; Invoke-Pester test/fullCLR -OutputFormat NUnitXml -OutputFile $testResultsFileFullCLR"
|
||||
(New-Object 'System.Net.WebClient').UploadFile("https://ci.appveyor.com/api/testresults/nunit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path $testResultsFileFullCLR))
|
||||
#
|
||||
# Fail the build, if tests failed
|
||||
@@ -71,8 +70,8 @@ on_finish:
|
||||
$zipFilePath = Join-Path $pwd "$name.zip"
|
||||
$zipFileFullPath = Join-Path $pwd "$name.FullCLR.zip"
|
||||
Add-Type -assemblyname System.IO.Compression.FileSystem
|
||||
[System.IO.Compression.ZipFile]::CreateFromDirectory("$pwd\bin", $zipFilePath)
|
||||
[System.IO.Compression.ZipFile]::CreateFromDirectory("$pwd\binFull", $zipFileFullPath)
|
||||
[System.IO.Compression.ZipFile]::CreateFromDirectory($env:CoreOutput, $zipFilePath)
|
||||
[System.IO.Compression.ZipFile]::CreateFromDirectory($env:FullOutput, $zipFileFullPath)
|
||||
|
||||
@(
|
||||
# You can add other artifacts here
|
||||
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo "Installing build dependencies"
|
||||
|
||||
curl http://llvm.org/apt/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||
echo "deb http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.6 main" | sudo tee /etc/apt/sources.list.d/llvm.list
|
||||
sudo apt-get update -qq
|
||||
|
||||
sudo apt-get install -y wget make g++ cmake \
|
||||
libc6 libgcc1 libstdc++6 \
|
||||
libcurl3 libgssapi-krb5-2 libicu52 liblldb-3.6 liblttng-ust0 libssl1.0.0 libunwind8 libuuid1 zlib1g clang-3.5
|
||||
|
||||
wget -P /tmp https://dotnetcli.blob.core.windows.net/dotnet/beta/Installers/Latest/dotnet-host-ubuntu-x64.latest.deb
|
||||
sudo dpkg -i /tmp/dotnet-host-ubuntu-x64.latest.deb
|
||||
|
||||
wget -P /tmp https://dotnetcli.blob.core.windows.net/dotnet/beta/Installers/Latest/dotnet-sharedframework-ubuntu-x64.latest.deb
|
||||
sudo dpkg -i /tmp/dotnet-sharedframework-ubuntu-x64.latest.deb
|
||||
|
||||
wget -P /tmp https://dotnetcli.blob.core.windows.net/dotnet/beta/Installers/Latest/dotnet-sdk-ubuntu-x64.latest.deb
|
||||
sudo dpkg -i /tmp/dotnet-sdk-ubuntu-x64.latest.deb
|
||||
@@ -5,7 +5,7 @@ hash cmake 2>/dev/null || { echo >&2 "No cmake, please run 'sudo apt-get install
|
||||
hash g++ 2>/dev/null || { echo >&2 "No g++, please run 'sudo apt-get install g++'"; exit 1; }
|
||||
hash dotnet 2>/dev/null || { echo >&2 "No dotnet, please visit https://dotnet.github.io/getting-started/"; exit 1; }
|
||||
|
||||
TOP="$(pwd)/src/Microsoft.PowerShell.Linux.Host"
|
||||
TOP="$(pwd)/src/Microsoft.PowerShell.Host"
|
||||
|
||||
# Test for lock file
|
||||
test -r "$TOP/project.lock.json" || { echo >&2 "Please run 'dotnet restore' to download .NET Core packages"; exit 2; }
|
||||
|
||||
@@ -42,3 +42,19 @@ provide a PID. (Please be careful not to commit such a change).
|
||||
[vscode]: https://code.visualstudio.com/
|
||||
[OmniSharp]: https://github.com/OmniSharp/omnisharp-vscode
|
||||
[vscclrdebugger]: http://aka.ms/vscclrdebugger
|
||||
|
||||
corehost
|
||||
--------
|
||||
|
||||
The native executable prouduced by .NET CLI will produce trace output
|
||||
if launched with `COREHOST_TRACE=1 ./powershell`.
|
||||
|
||||
CoreCLR PAL
|
||||
-----------
|
||||
|
||||
The native code in the CLR has debug channels to selectively output
|
||||
information to the console. These are controlled by the
|
||||
`PAL_DBG_CHANNELS`, e.g., `export PAL_DBG_CHANNELS="+all.all"`, as
|
||||
detailed in the `dbgmsg.h` [header][].
|
||||
|
||||
[header]: https://github.com/dotnet/coreclr/blob/release/1.0.0-rc2/src/pal/src/include/pal/dbgmsg.h
|
||||
+22
-1
@@ -1180,5 +1180,26 @@
|
||||
"src/monad/monad/nttargets/assemblies/nativemsh/pwrshcommon/WinSystemCallFacade.h": "src/powershell-native/nativemsh/pwrshcommon/WinSystemCallFacade.h",
|
||||
"src/monad/monad/nttargets/assemblies/nativemsh/pwrshexe/MainEntry.cpp": "src/powershell-native/nativemsh/pwrshexe/MainEntry.cpp",
|
||||
"src/monad/monad/nttargets/assemblies/nativemsh/pwrshexe/OutputWriter.h": "src/powershell-native/nativemsh/pwrshexe/OutputWriter.h",
|
||||
"src/monad/monad/src/graphicalhost/visualstudiopublic.snk": "src/signing/visualstudiopublic.snk"
|
||||
"src/monad/monad/src/graphicalhost/visualstudiopublic.snk": "src/signing/visualstudiopublic.snk",
|
||||
"src/monad/monad/miscfiles/modules/AppxProvider/AppxProvider.psd1": "src/Modules/AppxProvider/AppxProvider.psd1",
|
||||
"src/monad/monad/miscfiles/modules/AppxProvider/AppxProvider.psm1": "src/Modules/AppxProvider/AppxProvider.psm1",
|
||||
"src/monad/monad/miscfiles/modules/AppxProvider/AppxProvider.Resource.psd1": "src/Modules/AppxProvider/AppxProvider.Resource.psd1",
|
||||
"src/monad/monad/miscfiles/modules/Microsoft.PowerShell.Archive/ArchiveResources.psd1": "src/Modules/Microsoft.PowerShell.Archive/ArchiveResources.psd1",
|
||||
"src/monad/monad/miscfiles/modules/Microsoft.PowerShell.Archive/Microsoft.PowerShell.Archive.psd1": "src/Modules/Microsoft.PowerShell.Archive/Microsoft.PowerShell.Archive.psd1",
|
||||
"src/monad/monad/miscfiles/modules/Microsoft.PowerShell.Archive/Microsoft.PowerShell.Archive.psm1": "src/Modules/Microsoft.PowerShell.Archive/Microsoft.PowerShell.Archive.psm1",
|
||||
"src/monad/monad/miscfiles/modules/Microsoft.PowerShell.Diagnostics/CoreClr/Microsoft.PowerShell.Diagnostics.psd1": "src/Microsoft.PowerShell.Host/Modules/Microsoft.PowerShell.Diagnostics/Microsoft.PowerShell.Diagnostics.psd1",
|
||||
"src/monad/monad/miscfiles/modules/Microsoft.PowerShell.Diagnostics/Microsoft.PowerShell.Diagnostics.psd1": "src/Microsoft.PowerShell.ConsoleHost/Modules/Microsoft.PowerShell.Diagnostics/Microsoft.PowerShell.Diagnostics.psd1",
|
||||
"src/monad/monad/miscfiles/modules/Microsoft.PowerShell.Host/Microsoft.PowerShell.Host.psd1": "src/Modules/Microsoft.PowerShell.Host/Microsoft.PowerShell.Host.psd1",
|
||||
"src/monad/monad/miscfiles/modules/Microsoft.PowerShell.Management/Microsoft.PowerShell.Management.psd1": "src/Modules/Microsoft.PowerShell.Management/Microsoft.PowerShell.Management.psd1",
|
||||
"src/monad/monad/miscfiles/modules/Microsoft.PowerShell.Security/Microsoft.PowerShell.Security.psd1": "src/Modules/Microsoft.PowerShell.Security/Microsoft.PowerShell.Security.psd1",
|
||||
"src/monad/monad/miscfiles/modules/Microsoft.PowerShell.Utility/CoreClr/Microsoft.PowerShell.Utility.psd1": "src/Microsoft.PowerShell.Host/Modules/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1",
|
||||
"src/monad/monad/miscfiles/modules/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1": "src/Microsoft.PowerShell.ConsoleHost/Modules/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1",
|
||||
"src/monad/monad/miscfiles/modules/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psm1": "src/Modules/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psm1",
|
||||
"src/monad/monad/miscfiles/modules/Microsoft.WSMan.Management/Microsoft.WSMan.Management.psd1": "src/Modules/Microsoft.WSMan.Management/Microsoft.WSMan.Management.psd1",
|
||||
"src/monad/monad/miscfiles/modules/PSDiagnostics/PSDiagnostics.psd1": "src/Modules/PSDiagnostics/PSDiagnostics.psd1",
|
||||
"src/monad/monad/miscfiles/modules/PSDiagnostics/PSDiagnostics.psm1": "src/Modules/PSDiagnostics/PSDiagnostics.psm1",
|
||||
"src/monad/monad/miscfiles/modules/PSGet/PSGet.Format.ps1xml": "src/Modules/PSGet/PSGet.Format.ps1xml",
|
||||
"src/monad/monad/miscfiles/modules/PSGet/PSGet.psd1": "src/Modules/PSGet/PSGet.psd1",
|
||||
"src/monad/monad/miscfiles/modules/PSGet/PSGet.Resource.psd1": "src/Modules/PSGet/PSGet.Resource.psd1",
|
||||
"src/monad/monad/miscfiles/modules/PSGet/PSModule.psm1": "src/Modules/PSGet/PSModule.psm1"
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
test -x bin/powershell || { echo >&2 "No bin/powershell, please run './build.sh'"; exit 1; }
|
||||
|
||||
./bin/powershell --noprofile -c "Import-Module Microsoft.PowerShell.Platform; Invoke-Pester test/powershell/$1 -OutputFile pester-tests.xml -OutputFormat NUnitXml -EnableExit"
|
||||
failed_tests=$?
|
||||
|
||||
# XML files are not executable
|
||||
chmod -x pester-tests.xml
|
||||
|
||||
# Return number of failed tests as exit code (more than 0 will be an error)
|
||||
exit $failed_tests
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
@{
|
||||
GUID="CA046F10-CA64-4740-8FF9-2565DBA61A4F"
|
||||
Author="Microsoft Corporation"
|
||||
CompanyName="Microsoft Corporation"
|
||||
Copyright="© Microsoft Corporation. All rights reserved."
|
||||
ModuleVersion="3.0.0.0"
|
||||
PowerShellVersion="3.0"
|
||||
CLRVersion="4.0"
|
||||
AliasesToExport = @()
|
||||
FunctionsToExport = @()
|
||||
CmdletsToExport="Get-WinEvent", "Get-Counter", "Import-Counter", "Export-Counter", "New-WinEvent"
|
||||
NestedModules="Microsoft.PowerShell.Commands.Diagnostics.dll"
|
||||
TypesToProcess="GetEvent.types.ps1xml"
|
||||
FormatsToProcess="Event.format.ps1xml","Diagnostics.format.ps1xml"
|
||||
HelpInfoURI = 'http://go.microsoft.com/fwlink/?linkid=390783'
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
@{
|
||||
GUID="1DA87E53-152B-403E-98DC-74D7B4D63D59"
|
||||
Author="Microsoft Corporation"
|
||||
CompanyName="Microsoft Corporation"
|
||||
Copyright="© Microsoft Corporation. All rights reserved."
|
||||
ModuleVersion="3.1.0.0"
|
||||
PowerShellVersion="3.0"
|
||||
CLRVersion="4.0"
|
||||
CmdletsToExport= "Format-List", "Format-Custom", "Format-Table", "Format-Wide",
|
||||
"Out-File", "Out-Printer", "Out-String",
|
||||
"Out-GridView", "Get-FormatData", "Export-FormatData", "ConvertFrom-Json", "ConvertTo-Json",
|
||||
"Invoke-RestMethod", "Invoke-WebRequest", "Register-ObjectEvent", "Register-EngineEvent",
|
||||
"Wait-Event", "Get-Event", "Remove-Event", "Get-EventSubscriber", "Unregister-Event",
|
||||
"New-Event", "Add-Member", "Add-Type", "Compare-Object", "ConvertTo-Html", "ConvertFrom-StringData",
|
||||
"Export-Csv", "Import-Csv", "ConvertTo-Csv", "ConvertFrom-Csv", "Export-Alias", "Invoke-Expression",
|
||||
"Get-Alias", "Get-Culture", "Get-Date", "Get-Host", "Get-Member", "Get-Random", "Get-UICulture",
|
||||
"Get-Unique", "Export-PSSession", "Import-PSSession", "Import-Alias", "Import-LocalizedData",
|
||||
"Select-String", "Measure-Object", "New-Alias", "New-TimeSpan", "Read-Host", "Set-Alias", "Set-Date",
|
||||
"Start-Sleep", "Tee-Object", "Measure-Command", "Update-List", "Update-TypeData", "Update-FormatData",
|
||||
"Remove-TypeData", "Get-TypeData", "Write-Host", "Write-Progress", "New-Object", "Select-Object",
|
||||
"Group-Object", "Sort-Object", "Get-Variable", "New-Variable", "Set-Variable", "Remove-Variable",
|
||||
"Clear-Variable", "Export-Clixml", "Import-Clixml", "ConvertTo-Xml", "Select-Xml", "Write-Debug",
|
||||
"Write-Verbose", "Write-Warning", "Write-Error", "Write-Information", "Write-Output", "Set-PSBreakpoint", "Get-PSBreakpoint",
|
||||
"Remove-PSBreakpoint", "Enable-PSBreakpoint", "Disable-PSBreakpoint", "Get-PSCallStack",
|
||||
"Send-MailMessage", "Get-TraceSource", "Set-TraceSource", "Trace-Command", "Show-Command", "Unblock-File",
|
||||
"Get-Runspace", "Debug-Runspace", "Enable-RunspaceDebug", "Disable-RunspaceDebug", "Get-RunspaceDebug", "Wait-Debugger",
|
||||
"ConvertFrom-String", "Convert-String"
|
||||
FunctionsToExport= "Get-FileHash", "New-TemporaryFile", "New-Guid", "Format-Hex", "Import-PowerShellDataFile",
|
||||
"ConvertFrom-SddlString"
|
||||
AliasesToExport= "CFS", "fhx"
|
||||
NestedModules="Microsoft.PowerShell.Commands.Utility.dll","Microsoft.PowerShell.Utility.psm1"
|
||||
HelpInfoURI = 'http://go.microsoft.com/fwlink/?linkid=390787'
|
||||
}
|
||||
@@ -14,6 +14,12 @@
|
||||
"Microsoft.PowerShell.Commands.Utility": "1.0.0-*"
|
||||
},
|
||||
|
||||
"content": [
|
||||
"Modules",
|
||||
"../Modules",
|
||||
"powershell.exe"
|
||||
],
|
||||
|
||||
"frameworks": {
|
||||
"net451": {
|
||||
}
|
||||
|
||||
File renamed without changes.
File renamed without changes.
+13
@@ -0,0 +1,13 @@
|
||||
@{
|
||||
GUID="CA046F10-CA64-4740-8FF9-2565DBA61A4F"
|
||||
Author="Microsoft Corporation"
|
||||
CompanyName="Microsoft Corporation"
|
||||
Copyright="© Microsoft Corporation. All rights reserved."
|
||||
ModuleVersion="3.0.0.0"
|
||||
PowerShellVersion="3.0"
|
||||
CmdletsToExport="Get-WinEvent", "New-WinEvent"
|
||||
NestedModules="Microsoft.PowerShell.Commands.Diagnostics.dll"
|
||||
TypesToProcess="..\..\GetEvent.types.ps1xml"
|
||||
FormatsToProcess="..\..\Event.format.ps1xml"
|
||||
HelpInfoURI = 'http://go.microsoft.com/fwlink/?linkid=390783'
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,4 +1,4 @@
|
||||
namespace Microsoft.PowerShell.Linux.Host
|
||||
namespace Microsoft.PowerShell.Host
|
||||
{
|
||||
using System;
|
||||
using System.Globalization;
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Microsoft.PowerShell.Linux.Host
|
||||
namespace Microsoft.PowerShell.Host
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
+11
@@ -19,6 +19,7 @@
|
||||
|
||||
"content": [
|
||||
"Modules",
|
||||
"../Modules",
|
||||
"*_profile.ps1",
|
||||
"*.so",
|
||||
"*.dylib"
|
||||
@@ -28,5 +29,15 @@
|
||||
"netstandardapp1.5": {
|
||||
"imports": [ "dnxcore50", "portable-net45+win8" ]
|
||||
}
|
||||
},
|
||||
|
||||
"runtimes": {
|
||||
"ubuntu.14.04-x64": { },
|
||||
"centos.7.1-x64": { },
|
||||
"win7-x64": { },
|
||||
"win81-x64": { },
|
||||
"win10-x64": { },
|
||||
"osx.10.10-x64": { },
|
||||
"osx.10.11-x64": { }
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -10,7 +10,7 @@ using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Microsoft.PowerShell.Linux.Host
|
||||
namespace Microsoft.PowerShell.Host
|
||||
{
|
||||
// this is all from https://msdn.microsoft.com/en-us/library/ee706570%28v=vs.85%29.aspx
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
namespace Microsoft.PowerShell.Linux.Host
|
||||
namespace Microsoft.PowerShell.Host
|
||||
{
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Microsoft.PowerShell.Linux.Host
|
||||
namespace Microsoft.PowerShell.Host
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -1,26 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Types files
|
||||
cp ../monad/monad/miscfiles/types/CoreClr/types.ps1xml .
|
||||
cp ../monad/monad/miscfiles/types/CoreClr/typesv3.ps1xml .
|
||||
|
||||
# Format files
|
||||
cp ../monad/monad/miscfiles/display/Certificate.format.ps1xml .
|
||||
cp ../monad/monad/miscfiles/display/Diagnostics.Format.ps1xml Diagnostics.format.ps1xml
|
||||
cp ../monad/monad/miscfiles/display/DotNetTypes.format.ps1xml .
|
||||
cp ../monad/monad/miscfiles/display/Event.format.ps1xml .
|
||||
cp ../monad/monad/miscfiles/display/FileSystem.format.ps1xml .
|
||||
cp ../monad/monad/miscfiles/display/Help.format.ps1xml .
|
||||
cp ../monad/monad/miscfiles/display/HelpV3.format.ps1xml .
|
||||
cp ../monad/monad/miscfiles/display/PowerShellCore.format.ps1xml .
|
||||
cp ../monad/monad/miscfiles/display/PowerShellTrace.format.ps1xml .
|
||||
cp ../monad/monad/miscfiles/display/Registry.format.ps1xml .
|
||||
cp ../monad/monad/miscfiles/display/WSMan.format.ps1xml .
|
||||
|
||||
mkdir Modules
|
||||
cp -r ../monad/monad/miscfiles/modules/Microsoft.PowerShell.Utility Modules
|
||||
UTILSCLR=Modules/Microsoft.PowerShell.Utility/CoreClr
|
||||
mv $UTILSCLR/* Modules/Microsoft.PowerShell.Utility && rmdir $UTILSCLR
|
||||
cp -r ../monad/monad/miscfiles/modules/Microsoft.PowerShell.Security Modules
|
||||
cp -r ../monad/monad/miscfiles/modules/Microsoft.PowerShell.Management Modules
|
||||
cp -r ../monad/monad/miscfiles/modules/PSDiagnostics Modules
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,956 @@
|
||||
#########################################################################################
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
#
|
||||
# Appx Provider Module
|
||||
#
|
||||
#########################################################################################
|
||||
|
||||
$script:ProviderName = "appx"
|
||||
$script:AppxPackageExtension = ".appx"
|
||||
$script:AppxManifestFile = "AppxManifest.xml"
|
||||
$script:Architecture = "Architecture"
|
||||
$script:ResourceId = "ResourceId"
|
||||
$script:AppxPackageSources = $null
|
||||
$script:AppxLocalPath="$env:LOCALAPPDATA\Microsoft\Windows\PowerShell\AppxProvider"
|
||||
$script:AppxPackageSourcesFilePath = Microsoft.PowerShell.Management\Join-Path -Path $script:AppxLocalPath -ChildPath "AppxPackageSources.xml"
|
||||
$Script:ResponseUri = "ResponseUri"
|
||||
$Script:StatusCode = "StatusCode"
|
||||
# Wildcard pattern matching configuration.
|
||||
$script:wildcardOptions = [System.Management.Automation.WildcardOptions]::CultureInvariant -bor `
|
||||
[System.Management.Automation.WildcardOptions]::IgnoreCase
|
||||
#Localized Data
|
||||
Microsoft.PowerShell.Utility\Import-LocalizedData LocalizedData -filename AppxProvider.Resource.psd1
|
||||
|
||||
#region Appx Provider APIs Implementation
|
||||
function Get-PackageProviderName
|
||||
{
|
||||
return $script:ProviderName
|
||||
}
|
||||
|
||||
function Initialize-Provider{
|
||||
param(
|
||||
)
|
||||
}
|
||||
|
||||
function Get-DynamicOptions
|
||||
{
|
||||
param
|
||||
(
|
||||
[Microsoft.PackageManagement.MetaProvider.PowerShell.OptionCategory]
|
||||
$category
|
||||
)
|
||||
|
||||
Write-Debug ($LocalizedData.ProviderApiDebugMessage -f ('Get-DynamicOptions'))
|
||||
|
||||
switch($category)
|
||||
{
|
||||
Install {
|
||||
Write-Output -InputObject (New-DynamicOption -Category $category -Name Architecture -ExpectedType String -IsRequired $false)
|
||||
Write-Output -InputObject (New-DynamicOption -Category $category -Name ResourceId -ExpectedType String -IsRequired $false)
|
||||
}
|
||||
Package {
|
||||
Write-Output -InputObject (New-DynamicOption -Category $category -Name Architecture -ExpectedType String -IsRequired $false)
|
||||
Write-Output -InputObject (New-DynamicOption -Category $category -Name ResourceId -ExpectedType String -IsRequired $false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Find-Package
|
||||
{
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
[string[]]
|
||||
$names,
|
||||
|
||||
[string]
|
||||
$requiredVersion,
|
||||
|
||||
[string]
|
||||
$minimumVersion,
|
||||
|
||||
[string]
|
||||
$maximumVersion
|
||||
)
|
||||
|
||||
Write-Debug ($LocalizedData.ProviderApiDebugMessage -f ('Find-Package'))
|
||||
|
||||
$ResourceId = $null
|
||||
$Architecture = $null
|
||||
$Sources = @()
|
||||
$streamedResults = @()
|
||||
$namesParameterEmpty = (-not $names) -or (($names.Count -eq 1) -and ($names[0] -eq ''))
|
||||
|
||||
Set-PackageSourcesVariable
|
||||
|
||||
if($RequiredVersion -and $MinimumVersion)
|
||||
{
|
||||
|
||||
ThrowError -ExceptionName "System.ArgumentException" `
|
||||
-ExceptionMessage $LocalizedData.VersionRangeAndRequiredVersionCannotBeSpecifiedTogether `
|
||||
-ErrorId "VersionRangeAndRequiredVersionCannotBeSpecifiedTogether" `
|
||||
-CallerPSCmdlet $PSCmdlet `
|
||||
-ErrorCategory InvalidArgument
|
||||
}
|
||||
if($RequiredVersion -or $MinimumVersion)
|
||||
{
|
||||
if(-not $names -or $names.Count -ne 1 -or (Test-WildcardPattern -Name $names[0]))
|
||||
{
|
||||
ThrowError -ExceptionName "System.ArgumentException" `
|
||||
-ExceptionMessage $LocalizedData.VersionParametersAreAllowedOnlyWithSinglePackage `
|
||||
-ErrorId "VersionParametersAreAllowedOnlyWithSinglePackage" `
|
||||
-CallerPSCmdlet $PSCmdlet `
|
||||
-ErrorCategory InvalidArgument
|
||||
}
|
||||
}
|
||||
|
||||
$options = $request.Options
|
||||
if($options)
|
||||
{
|
||||
foreach( $o in $options.Keys )
|
||||
{
|
||||
Write-Debug ( "OPTION: {0} => {1}" -f ($o, $options[$o]) )
|
||||
}
|
||||
|
||||
if($options.ContainsKey('Source'))
|
||||
{
|
||||
$SourceNames = $($options['Source'])
|
||||
Write-Verbose ($LocalizedData.SpecifiedSourceName -f ($SourceNames))
|
||||
foreach($sourceName in $SourceNames)
|
||||
{
|
||||
if($script:AppxPackageSources.Contains($sourceName))
|
||||
{
|
||||
$Sources += $script:AppxPackageSources[$sourceName]
|
||||
}
|
||||
else
|
||||
{
|
||||
$sourceByLocation = Get-SourceName -Location $sourceName
|
||||
if ($sourceByLocation -ne $null)
|
||||
{
|
||||
$Sources += $script:AppxPackageSources[$sourceByLocation]
|
||||
}
|
||||
else
|
||||
{
|
||||
$message = $LocalizedData.PackageSourceNotFound -f ($sourceName)
|
||||
ThrowError -ExceptionName "System.ArgumentException" `
|
||||
-ExceptionMessage $message `
|
||||
-ErrorId "PackageSourceNotFound" `
|
||||
-CallerPSCmdlet $PSCmdlet `
|
||||
-ErrorCategory InvalidArgument `
|
||||
-ExceptionObject $sourceName
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Verbose $LocalizedData.NoSourceNameIsSpecified
|
||||
$script:AppxPackageSources.Values | Microsoft.PowerShell.Core\ForEach-Object { $Sources += $_ }
|
||||
}
|
||||
|
||||
if($options.ContainsKey($script:Architecture))
|
||||
{
|
||||
$Architecture = $options[$script:Architecture]
|
||||
}
|
||||
if($options.ContainsKey($script:ResourceId))
|
||||
{
|
||||
$ResourceId = $options[$script:ResourceId]
|
||||
}
|
||||
}
|
||||
|
||||
foreach($source in $Sources)
|
||||
{
|
||||
$location = $source.SourceLocation
|
||||
if($request.IsCanceled)
|
||||
{
|
||||
return
|
||||
}
|
||||
if(-not(Test-Path $location))
|
||||
{
|
||||
$message = $LocalizedData.PathNotFound -f ($Location)
|
||||
Write-Verbose $message
|
||||
continue
|
||||
}
|
||||
|
||||
$packages = Get-AppxPackagesFromPath -path $location
|
||||
foreach($pkg in $packages)
|
||||
{
|
||||
if($request.IsCanceled)
|
||||
{
|
||||
return
|
||||
}
|
||||
|
||||
$pkgManifest = Get-PackageManfiestData -PackageFullPath $pkg.FullName
|
||||
if(-not $pkgManifest)
|
||||
{
|
||||
continue
|
||||
}
|
||||
|
||||
# $pkgManifest.Name has to match any of the supplied names, using PowerShell wildcards
|
||||
if(-not($namesParameterEmpty))
|
||||
{
|
||||
if(-not(($names | Microsoft.PowerShell.Core\ForEach-Object { if ($pkgManifest.Name -like $_){return $true; break} } -End {return $false})))
|
||||
{
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
# Version
|
||||
if($RequiredVersion)
|
||||
{
|
||||
if($RequiredVersion -ne $pkgManifest.Version)
|
||||
{
|
||||
continue
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(-not((-not $MinimumVersion -or ($MinimumVersion -le $pkgManifest.Version)) -and
|
||||
(-not $MaximumVersion -or ($MaximumVersion -ge $pkgManifest.Version))))
|
||||
{
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if($Architecture)
|
||||
{
|
||||
$wildcardPattern = New-Object System.Management.Automation.WildcardPattern $Architecture, $script:wildcardOptions
|
||||
if(-not($wildcardPattern.IsMatch($pkgManifest.Architecture)))
|
||||
{
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if($ResourceId)
|
||||
{
|
||||
$wildcardPattern = New-Object System.Management.Automation.WildcardPattern $ResourceId, $script:wildcardOptions
|
||||
if(-not($wildcardPattern.IsMatch($pkgManifest.ResourceId)))
|
||||
{
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
$sid = New-SoftwareIdentityFromPackage -Package $pkgManifest -Source $source.Name
|
||||
$fastPackageReference = $sid.fastPackageReference
|
||||
if($streamedResults -notcontains $fastPackageReference)
|
||||
{
|
||||
$streamedResults += $fastPackageReference
|
||||
Write-Output -InputObject $sid
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Get-InstalledPackage
|
||||
{
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
[Parameter()]
|
||||
[string]
|
||||
$Name,
|
||||
|
||||
[Parameter()]
|
||||
[string]
|
||||
$RequiredVersion,
|
||||
|
||||
[Parameter()]
|
||||
[string]
|
||||
$MinimumVersion,
|
||||
|
||||
[Parameter()]
|
||||
[string]
|
||||
$MaximumVersion
|
||||
)
|
||||
|
||||
Write-Debug -Message ($LocalizedData.ProviderApiDebugMessage -f ('Get-InstalledPackage'))
|
||||
|
||||
$Architecture = $null
|
||||
$ResourceId = $null
|
||||
|
||||
$options = $request.Options
|
||||
if($options)
|
||||
{
|
||||
if($options.ContainsKey($script:Architecture))
|
||||
{
|
||||
$Architecture = $options[$script:Architecture]
|
||||
}
|
||||
if($options.ContainsKey($script:ResourceId))
|
||||
{
|
||||
$ResourceId = $options[$script:ResourceId]
|
||||
}
|
||||
}
|
||||
|
||||
$params = @{}
|
||||
if($Name)
|
||||
{
|
||||
$params.Add("Name", $Name)
|
||||
}
|
||||
$packages = Appx\Get-AppxPackage @params
|
||||
|
||||
foreach($package in $packages)
|
||||
{
|
||||
if($RequiredVersion)
|
||||
{
|
||||
if($RequiredVersion -ne $package.Version)
|
||||
{
|
||||
continue
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(-not((-not $MinimumVersion -or ($MinimumVersion -le $package.Version)) -and
|
||||
(-not $MaximumVersion -or ($MaximumVersion -ge $package.Version))))
|
||||
{
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if($Architecture)
|
||||
{
|
||||
$wildcardPattern = New-Object System.Management.Automation.WildcardPattern $Architecture, $script:wildcardOptions
|
||||
if(-not($wildcardPattern.IsMatch($package.Architecture)))
|
||||
{
|
||||
continue
|
||||
}
|
||||
}
|
||||
if($ResourceId)
|
||||
{
|
||||
$wildcardPattern = New-Object System.Management.Automation.WildcardPattern $ResourceId,$script:wildcardOptions
|
||||
if(-not($wildcardPattern.IsMatch($package.ResourceId)))
|
||||
{
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
$sid = New-SoftwareIdentityFromPackage -Package $package
|
||||
write-Output $sid
|
||||
}
|
||||
}
|
||||
|
||||
function Install-Package
|
||||
{
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string]
|
||||
$fastPackageReference
|
||||
)
|
||||
|
||||
Write-Debug -Message ($LocalizedData.ProviderApiDebugMessage -f ('Install-Package'))
|
||||
Write-Debug -Message ($LocalizedData.FastPackageReference -f $fastPackageReference)
|
||||
|
||||
Appx\Add-AppxPackage -Path $fastPackageReference
|
||||
}
|
||||
|
||||
function UnInstall-Package
|
||||
{
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string]
|
||||
$fastPackageReference
|
||||
)
|
||||
|
||||
Write-Debug -Message ($LocalizedData.ProviderApiDebugMessage -f ('Uninstall-Package'))
|
||||
Write-Debug -Message ($LocalizedData.FastPackageReference -f $fastPackageReference)
|
||||
|
||||
Appx\Remove-AppxPackage -Package $fastPackageReference
|
||||
}
|
||||
|
||||
function Add-PackageSource
|
||||
{
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
[string]
|
||||
$Name,
|
||||
|
||||
[string]
|
||||
$Location,
|
||||
|
||||
[bool]
|
||||
$Trusted
|
||||
)
|
||||
|
||||
Write-Debug ($LocalizedData.ProviderApiDebugMessage -f ('Add-PackageSource'))
|
||||
|
||||
Set-PackageSourcesVariable -Force
|
||||
|
||||
if(-not (Microsoft.PowerShell.Management\Test-Path $Location) -and
|
||||
-not (Test-WebUri -uri $Location))
|
||||
{
|
||||
$LocationUri = [Uri]$Location
|
||||
if($LocationUri.Scheme -eq 'file')
|
||||
{
|
||||
$message = $LocalizedData.PathNotFound -f ($Location)
|
||||
ThrowError -ExceptionName "System.ArgumentException" `
|
||||
-ExceptionMessage $message `
|
||||
-ErrorId "PathNotFound" `
|
||||
-CallerPSCmdlet $PSCmdlet `
|
||||
-ErrorCategory InvalidArgument `
|
||||
-ExceptionObject $Location
|
||||
}
|
||||
else
|
||||
{
|
||||
$message = $LocalizedData.InvalidWebUri -f ($Location, "Location")
|
||||
ThrowError -ExceptionName "System.ArgumentException" `
|
||||
-ExceptionMessage $message `
|
||||
-ErrorId "InvalidWebUri" `
|
||||
-CallerPSCmdlet $PSCmdlet `
|
||||
-ErrorCategory InvalidArgument `
|
||||
-ExceptionObject $Location
|
||||
}
|
||||
}
|
||||
|
||||
if(Test-WildcardPattern $Name)
|
||||
{
|
||||
$message = $LocalizedData.PackageSourceNameContainsWildCards -f ($Name)
|
||||
ThrowError -ExceptionName "System.ArgumentException" `
|
||||
-ExceptionMessage $message `
|
||||
-ErrorId "PackageSourceNameContainsWildCards" `
|
||||
-CallerPSCmdlet $PSCmdlet `
|
||||
-ErrorCategory InvalidArgument `
|
||||
-ExceptionObject $Name
|
||||
}
|
||||
|
||||
$LocationString = Get-ValidPackageLocation -LocationString $Location -ParameterName "Location"
|
||||
|
||||
# Check if Location is already registered with another Name
|
||||
$existingSourceName = Get-SourceName -Location $LocationString
|
||||
|
||||
if($existingSourceName -and
|
||||
($Name -ne $existingSourceName))
|
||||
{
|
||||
$message = $LocalizedData.PackageSourceAlreadyRegistered -f ($existingSourceName, $Location, $Name)
|
||||
ThrowError -ExceptionName "System.ArgumentException" `
|
||||
-ExceptionMessage $message `
|
||||
-ErrorId "PackageSourceAlreadyRegistered" `
|
||||
-CallerPSCmdlet $PSCmdlet `
|
||||
-ErrorCategory InvalidArgument
|
||||
}
|
||||
|
||||
# Check if Name is already registered
|
||||
if($script:AppxPackageSources.Contains($Name))
|
||||
{
|
||||
$currentSourceObject = $script:AppxPackageSources[$Name]
|
||||
$null = $script:AppxPackageSources.Remove($Name)
|
||||
}
|
||||
|
||||
# Add new package source
|
||||
$packageSource = Microsoft.PowerShell.Utility\New-Object PSCustomObject -Property ([ordered]@{
|
||||
Name = $Name
|
||||
SourceLocation = $LocationString
|
||||
Trusted=$Trusted
|
||||
Registered= $true
|
||||
})
|
||||
|
||||
$script:AppxPackageSources.Add($Name, $packageSource)
|
||||
$message = $LocalizedData.SourceRegistered -f ($Name, $LocationString)
|
||||
Write-Verbose $message
|
||||
|
||||
# Persist the package sources
|
||||
Save-PackageSources
|
||||
|
||||
# return the package source object.
|
||||
Write-Output -InputObject (New-PackageSourceFromSource -Source $packageSource)
|
||||
|
||||
}
|
||||
|
||||
function Resolve-PackageSource
|
||||
{
|
||||
Write-Debug ($LocalizedData.ProviderApiDebugMessage -f ('Resolve-PackageSource'))
|
||||
|
||||
Set-PackageSourcesVariable
|
||||
|
||||
$SourceName = $request.PackageSources
|
||||
|
||||
if(-not $SourceName)
|
||||
{
|
||||
$SourceName = "*"
|
||||
}
|
||||
|
||||
foreach($src in $SourceName)
|
||||
{
|
||||
if($request.IsCanceled)
|
||||
{
|
||||
return
|
||||
}
|
||||
|
||||
$wildcardPattern = New-Object System.Management.Automation.WildcardPattern $src,$script:wildcardOptions
|
||||
$sourceFound = $false
|
||||
|
||||
$script:AppxPackageSources.GetEnumerator() |
|
||||
Microsoft.PowerShell.Core\Where-Object {$wildcardPattern.IsMatch($_.Key)} |
|
||||
Microsoft.PowerShell.Core\ForEach-Object {
|
||||
$source = $script:AppxPackageSources[$_.Key]
|
||||
$packageSource = New-PackageSourceFromSource -Source $source
|
||||
Write-Output -InputObject $packageSource
|
||||
$sourceFound = $true
|
||||
}
|
||||
|
||||
if(-not $sourceFound)
|
||||
{
|
||||
$sourceName = Get-SourceName -Location $src
|
||||
if($sourceName)
|
||||
{
|
||||
$source = $script:AppxPackageSources[$sourceName]
|
||||
$packageSource = New-PackageSourceFromSource -Source $source
|
||||
Write-Output -InputObject $packageSource
|
||||
}
|
||||
elseif( -not (Test-WildcardPattern $src))
|
||||
{
|
||||
$message = $LocalizedData.PackageSourceNotFound -f ($src)
|
||||
Write-Error -Message $message -ErrorId "PackageSourceNotFound" -Category InvalidOperation -TargetObject $src
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Remove-PackageSource
|
||||
{
|
||||
param
|
||||
(
|
||||
[string]
|
||||
$Name
|
||||
)
|
||||
|
||||
Write-Debug ($LocalizedData.ProviderApiDebugMessage -f ('Remove-PackageSource'))
|
||||
|
||||
Set-PackageSourcesVariable -Force
|
||||
|
||||
$SourcesToBeRemoved = @()
|
||||
|
||||
foreach ($sourceName in $Name)
|
||||
{
|
||||
if($request.IsCanceled)
|
||||
{
|
||||
return
|
||||
}
|
||||
|
||||
# Check if $Name contains any wildcards
|
||||
if(Test-WildcardPattern $sourceName)
|
||||
{
|
||||
$message = $LocalizedData.PackageSourceNameContainsWildCards -f ($sourceName)
|
||||
Write-Error -Message $message -ErrorId "PackageSourceNameContainsWildCards" -Category InvalidOperation -TargetObject $sourceName
|
||||
continue
|
||||
}
|
||||
|
||||
# Check if the specified package source name is in the registered package sources
|
||||
if(-not $script:AppxPackageSources.Contains($sourceName))
|
||||
{
|
||||
$message = $LocalizedData.PackageSourceNotFound -f ($sourceName)
|
||||
Write-Error -Message $message -ErrorId "PackageSourceNotFound" -Category InvalidOperation -TargetObject $sourceName
|
||||
continue
|
||||
}
|
||||
|
||||
$SourcesToBeRemoved += $sourceName
|
||||
$message = $LocalizedData.PackageSourceUnregistered -f ($sourceName)
|
||||
Write-Verbose $message
|
||||
}
|
||||
|
||||
# Remove the SourcesToBeRemoved
|
||||
$SourcesToBeRemoved | Microsoft.PowerShell.Core\ForEach-Object { $null = $script:AppxPackageSources.Remove($_) }
|
||||
|
||||
# Persist the package sources
|
||||
Save-PackageSources
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Common functions
|
||||
|
||||
function Get-AppxPackagesFromPath
|
||||
{
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory=$true)]
|
||||
$Path
|
||||
)
|
||||
|
||||
$filterAppxPackages = "*"+$script:AppxPackageExtension
|
||||
$packages = Get-ChildItem -path $Path -filter $filterAppxPackages
|
||||
|
||||
return $packages
|
||||
|
||||
}
|
||||
|
||||
function Get-PackageManfiestData
|
||||
{
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory=$true)]
|
||||
$PackageFullPath
|
||||
)
|
||||
$guid = [System.Guid]::NewGuid().toString()
|
||||
try
|
||||
{
|
||||
[System.IO.Compression.ZipFile]::ExtractToDirectory($PackageFullPath, "$env:TEMP\$guid")
|
||||
}
|
||||
catch
|
||||
{
|
||||
Write-Verbose( $LocalizedData.MetaDataExtractionFailed -f ($PackageFullPath) )
|
||||
return $null
|
||||
}
|
||||
|
||||
[xml] $packageManifest = Get-Content "$env:TEMP\$guid\$script:AppxManifestFile" -ErrorAction SilentlyContinue
|
||||
if($packageManifest)
|
||||
{
|
||||
$Identity = $packageManifest.Package.Identity
|
||||
$manifestData = new-object psObject -Property @{Name=$Identity.Name; Architecture=$Identity.ProcessorArchitecture; Publisher=$Identity.Publisher; Version=$Identity.Version; ResourceId=$Identity.resourceId; PackageFullName=$PackageFullPath}
|
||||
Remove-Item -Path "$env:TEMP\$guid" -Recurse -Force -ErrorAction SilentlyContinue
|
||||
return $manifestData
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Verbose ($LocalizedData.MetaDataExtractionFailed -f ($PackageFullPath) )
|
||||
}
|
||||
return $null
|
||||
}
|
||||
|
||||
function New-FastPackageReference
|
||||
{
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]
|
||||
$PackageFullName
|
||||
)
|
||||
return "$PackageFullName"
|
||||
}
|
||||
|
||||
function New-SoftwareIdentityFromPackage
|
||||
{
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory=$true)]
|
||||
$Package,
|
||||
|
||||
[string]
|
||||
$Source
|
||||
|
||||
)
|
||||
|
||||
$fastPackageReference = New-FastPackageReference -PackageFullName $Package.PackageFullName
|
||||
|
||||
if(-not($Source))
|
||||
{
|
||||
$Source = $Package.Publisher
|
||||
}
|
||||
$details = @{
|
||||
Publisher = $Package.Publisher
|
||||
Architecture = $Package.Architecture
|
||||
ResourceId = $Package.ResourceId
|
||||
PackageFullName = $Package.PackageFullName
|
||||
}
|
||||
|
||||
$params = @{
|
||||
FastPackageReference = $fastPackageReference;
|
||||
Name = $Package.Name;
|
||||
Version = $Package.Version;
|
||||
versionScheme = "MultiPartNumeric";
|
||||
Source = $source;
|
||||
Details = $details;
|
||||
}
|
||||
|
||||
$sid = New-SoftwareIdentity @params
|
||||
return $sid
|
||||
}
|
||||
|
||||
function Test-WebUri
|
||||
{
|
||||
[CmdletBinding()]
|
||||
[OutputType([bool])]
|
||||
Param
|
||||
(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Uri]
|
||||
$uri
|
||||
)
|
||||
|
||||
return ($uri.AbsoluteURI -ne $null) -and ($uri.Scheme -match '[http|https]')
|
||||
}
|
||||
|
||||
function Test-WildcardPattern
|
||||
{
|
||||
[CmdletBinding()]
|
||||
[OutputType([bool])]
|
||||
param(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[ValidateNotNull()]
|
||||
$Name
|
||||
)
|
||||
|
||||
return [System.Management.Automation.WildcardPattern]::ContainsWildcardCharacters($Name)
|
||||
}
|
||||
|
||||
function DeSerialize-PSObject
|
||||
{
|
||||
[CmdletBinding(PositionalBinding=$false)]
|
||||
Param
|
||||
(
|
||||
[Parameter(Mandatory=$true)]
|
||||
$Path
|
||||
)
|
||||
$filecontent = Microsoft.PowerShell.Management\Get-Content -Path $Path
|
||||
[System.Management.Automation.PSSerializer]::Deserialize($filecontent)
|
||||
}
|
||||
|
||||
function Get-SourceName
|
||||
{
|
||||
[CmdletBinding()]
|
||||
[OutputType("string")]
|
||||
Param
|
||||
(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string]
|
||||
$Location
|
||||
)
|
||||
|
||||
Set-PackageSourcesVariable
|
||||
|
||||
foreach($source in $script:AppxPackageSources.Values)
|
||||
{
|
||||
if($source.SourceLocation -eq $Location)
|
||||
{
|
||||
return $source.Name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function WebRequestApisAvailable
|
||||
{
|
||||
$webRequestApiAvailable = $false
|
||||
try
|
||||
{
|
||||
[System.Net.WebRequest]
|
||||
$webRequestApiAvailable = $true
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
return $webRequestApiAvailable
|
||||
}
|
||||
|
||||
function Ping-Endpoint
|
||||
{
|
||||
param
|
||||
(
|
||||
[Parameter()]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string[]]
|
||||
$Endpoint
|
||||
)
|
||||
|
||||
$results = @{}
|
||||
|
||||
if(WebRequestApisAvailable)
|
||||
{
|
||||
$iss = [System.Management.Automation.Runspaces.InitialSessionState]::Create()
|
||||
$iss.types.clear()
|
||||
$iss.formats.clear()
|
||||
$iss.LanguageMode = "FullLanguage"
|
||||
|
||||
$WebRequestcmd = @'
|
||||
try
|
||||
{{
|
||||
$request = [System.Net.WebRequest]::Create("{0}")
|
||||
$request.Method = 'GET'
|
||||
$request.Timeout = 30000
|
||||
$response = [System.Net.HttpWebResponse]$request.GetResponse()
|
||||
$response
|
||||
$response.Close()
|
||||
}}
|
||||
catch [System.Net.WebException]
|
||||
{{
|
||||
"Error:System.Net.WebException"
|
||||
}}
|
||||
'@ -f $EndPoint
|
||||
|
||||
$ps = [powershell]::Create($iss).AddScript($WebRequestcmd)
|
||||
$response = $ps.Invoke()
|
||||
$ps.dispose()
|
||||
|
||||
if ($response -ne "Error:System.Net.WebException")
|
||||
{
|
||||
$results.Add($Script:ResponseUri,$response.ResponseUri.ToString())
|
||||
$results.Add($Script:StatusCode,$response.StatusCode.value__)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$response = $null
|
||||
try
|
||||
{
|
||||
$httpClient = New-Object 'System.Net.Http.HttpClient'
|
||||
$response = $httpclient.GetAsync($endpoint)
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
if ($response -ne $null -and $response.result -ne $null)
|
||||
{
|
||||
$results.Add($Script:ResponseUri,$response.Result.RequestMessage.RequestUri.AbsoluteUri.ToString())
|
||||
$results.Add($Script:StatusCode,$response.result.StatusCode.value__)
|
||||
}
|
||||
}
|
||||
return $results
|
||||
}
|
||||
|
||||
function Get-ValidPackageLocation
|
||||
{
|
||||
[CmdletBinding()]
|
||||
Param
|
||||
(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string]
|
||||
$LocationString,
|
||||
|
||||
[Parameter(Mandatory=$true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string]
|
||||
$ParameterName
|
||||
)
|
||||
|
||||
# Get the actual Uri from the Location
|
||||
if(-not (Microsoft.PowerShell.Management\Test-Path $LocationString))
|
||||
{
|
||||
$results = Ping-Endpoint -Endpoint $LocationString
|
||||
|
||||
if ($results.ContainsKey("Exception"))
|
||||
{
|
||||
$Exception = $results["Exception"]
|
||||
if($Exception)
|
||||
{
|
||||
$message = $LocalizedData.InvalidWebUri -f ($LocationString, $ParameterName)
|
||||
ThrowError -ExceptionName "System.ArgumentException" `
|
||||
-ExceptionMessage $message `
|
||||
-ErrorId "InvalidWebUri" `
|
||||
-ExceptionObject $Exception `
|
||||
-CallerPSCmdlet $PSCmdlet `
|
||||
-ErrorCategory InvalidArgument
|
||||
}
|
||||
}
|
||||
|
||||
if ($results.ContainsKey("ResponseUri"))
|
||||
{
|
||||
$LocationString = $results["ResponseUri"]
|
||||
}
|
||||
}
|
||||
|
||||
return $LocationString
|
||||
}
|
||||
|
||||
function Set-PackageSourcesVariable
|
||||
{
|
||||
param([switch]$Force)
|
||||
|
||||
if(-not $script:AppxPackageSources -or $Force)
|
||||
{
|
||||
if(Microsoft.PowerShell.Management\Test-Path $script:AppxPackageSourcesFilePath)
|
||||
{
|
||||
$script:AppxPackageSources = DeSerialize-PSObject -Path $script:AppxPackageSourcesFilePath
|
||||
}
|
||||
else
|
||||
{
|
||||
$script:AppxPackageSources = [ordered]@{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Save-PackageSources
|
||||
{
|
||||
if($script:AppxPackageSources)
|
||||
{
|
||||
if(-not (Microsoft.PowerShell.Management\Test-Path $script:AppxLocalPath))
|
||||
{
|
||||
$null = Microsoft.PowerShell.Management\New-Item -Path $script:AppxLocalPath `
|
||||
-ItemType Directory -Force `
|
||||
-ErrorAction SilentlyContinue `
|
||||
-WarningAction SilentlyContinue `
|
||||
-Confirm:$false -WhatIf:$false
|
||||
}
|
||||
Microsoft.PowerShell.Utility\Out-File -FilePath $script:AppxPackageSourcesFilePath -Force -InputObject ([System.Management.Automation.PSSerializer]::Serialize($script:AppxPackageSources))
|
||||
}
|
||||
}
|
||||
|
||||
function New-PackageSourceFromSource
|
||||
{
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory)]
|
||||
$Source
|
||||
)
|
||||
|
||||
# create a new package source
|
||||
$src = New-PackageSource -Name $Source.Name `
|
||||
-Location $Source.SourceLocation `
|
||||
-Trusted $Source.Trusted `
|
||||
-Registered $Source.Registered `
|
||||
|
||||
Write-Verbose ( $LocalizedData.PackageSourceDetails -f ($src.Name, $src.Location, $src.IsTrusted, $src.IsRegistered) )
|
||||
|
||||
# return the package source object.
|
||||
Write-Output -InputObject $src
|
||||
}
|
||||
#endregion
|
||||
|
||||
# Utility to throw an errorrecord
|
||||
function ThrowError
|
||||
{
|
||||
param
|
||||
(
|
||||
[parameter(Mandatory = $true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[System.Management.Automation.PSCmdlet]
|
||||
$CallerPSCmdlet,
|
||||
|
||||
[parameter(Mandatory = $true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[System.String]
|
||||
$ExceptionName,
|
||||
|
||||
[parameter(Mandatory = $true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[System.String]
|
||||
$ExceptionMessage,
|
||||
|
||||
[System.Object]
|
||||
$ExceptionObject,
|
||||
|
||||
[parameter(Mandatory = $true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[System.String]
|
||||
$ErrorId,
|
||||
|
||||
[parameter(Mandatory = $true)]
|
||||
[ValidateNotNull()]
|
||||
[System.Management.Automation.ErrorCategory]
|
||||
$ErrorCategory
|
||||
)
|
||||
|
||||
$exception = New-Object $ExceptionName $ExceptionMessage;
|
||||
$errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $ErrorId, $ErrorCategory, $ExceptionObject
|
||||
$CallerPSCmdlet.ThrowTerminatingError($errorRecord)
|
||||
}
|
||||
#endregion
|
||||
|
||||
Export-ModuleMember -Function Find-Package, `
|
||||
Install-Package, `
|
||||
Uninstall-Package, `
|
||||
Get-InstalledPackage, `
|
||||
Remove-PackageSource, `
|
||||
Resolve-PackageSource, `
|
||||
Add-PackageSource, `
|
||||
Get-DynamicOptions, `
|
||||
Initialize-Provider, `
|
||||
Get-PackageProviderName
|
||||
Binary file not shown.
@@ -0,0 +1,12 @@
|
||||
@{
|
||||
GUID="eb74e8da-9ae2-482a-a648-e96550fb8733"
|
||||
Author="Microsoft Corporation"
|
||||
CompanyName="Microsoft Corporation"
|
||||
Copyright="© Microsoft Corporation. All rights reserved."
|
||||
ModuleVersion="1.0.0.0"
|
||||
FunctionsToExport = @('Compress-Archive', 'Expand-Archive')
|
||||
CmdletsToExport = @()
|
||||
AliasesToExport = @()
|
||||
NestedModules="Microsoft.PowerShell.Archive.psm1"
|
||||
HelpInfoURI = 'http://go.microsoft.com/fwlink/?LinkId=393254'
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,14 @@
|
||||
@{
|
||||
GUID="56D66100-99A0-4FFC-A12D-EEE9A6718AEF"
|
||||
Author="Microsoft Corporation"
|
||||
CompanyName="Microsoft Corporation"
|
||||
Copyright="© Microsoft Corporation. All rights reserved."
|
||||
ModuleVersion="3.0.0.0"
|
||||
PowerShellVersion="3.0"
|
||||
CLRVersion="4.0"
|
||||
AliasesToExport = @()
|
||||
FunctionsToExport = @()
|
||||
CmdletsToExport="Start-Transcript", "Stop-Transcript"
|
||||
NestedModules="Microsoft.PowerShell.ConsoleHost.dll"
|
||||
HelpInfoURI = 'http://go.microsoft.com/fwlink/?linkid=390784'
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
@{
|
||||
GUID="EEFCB906-B326-4E99-9F54-8B4BB6EF3C6D"
|
||||
Author="Microsoft Corporation"
|
||||
CompanyName="Microsoft Corporation"
|
||||
Copyright="© Microsoft Corporation. All rights reserved."
|
||||
ModuleVersion="3.1.0.0"
|
||||
PowerShellVersion="3.0"
|
||||
CLRVersion="4.0"
|
||||
NestedModules="Microsoft.PowerShell.Commands.Management.dll"
|
||||
HelpInfoURI = 'http://go.microsoft.com/fwlink/?linkid=390785'
|
||||
AliasesToExport = @("gcb", "scb")
|
||||
FunctionsToExport = @()
|
||||
CmdletsToExport=@("Add-Content",
|
||||
"Clear-Content",
|
||||
"Clear-ItemProperty",
|
||||
"Join-Path",
|
||||
"Convert-Path",
|
||||
"Copy-ItemProperty",
|
||||
"Get-EventLog",
|
||||
"Clear-EventLog",
|
||||
"Write-EventLog",
|
||||
"Limit-EventLog",
|
||||
"Show-EventLog",
|
||||
"New-EventLog",
|
||||
"Remove-EventLog",
|
||||
"Get-ChildItem",
|
||||
"Get-Content",
|
||||
"Get-ItemProperty",
|
||||
"Get-ItemPropertyValue",
|
||||
"Get-WmiObject",
|
||||
"Invoke-WmiMethod",
|
||||
"Move-ItemProperty",
|
||||
"Get-Location",
|
||||
"Set-Location",
|
||||
"Push-Location",
|
||||
"Pop-Location",
|
||||
"New-PSDrive",
|
||||
"Remove-PSDrive",
|
||||
"Get-PSDrive",
|
||||
"Get-Item",
|
||||
"New-Item",
|
||||
"Set-Item",
|
||||
"Remove-Item",
|
||||
"Move-Item",
|
||||
"Rename-Item",
|
||||
"Copy-Item",
|
||||
"Clear-Item",
|
||||
"Invoke-Item",
|
||||
"Get-PSProvider",
|
||||
"New-ItemProperty",
|
||||
"Split-Path",
|
||||
"Test-Path",
|
||||
"Get-Process",
|
||||
"Stop-Process",
|
||||
"Wait-Process",
|
||||
"Debug-Process",
|
||||
"Start-Process",
|
||||
"Remove-ItemProperty",
|
||||
"Remove-WmiObject",
|
||||
"Rename-ItemProperty",
|
||||
"Register-WmiEvent",
|
||||
"Resolve-Path",
|
||||
"Get-Service",
|
||||
"Stop-Service",
|
||||
"Start-Service",
|
||||
"Suspend-Service",
|
||||
"Resume-Service",
|
||||
"Restart-Service",
|
||||
"Set-Service",
|
||||
"New-Service",
|
||||
"Set-Content",
|
||||
"Set-ItemProperty",
|
||||
"Set-WmiInstance",
|
||||
"Get-Transaction",
|
||||
"Start-Transaction",
|
||||
"Complete-Transaction",
|
||||
"Undo-Transaction",
|
||||
"Use-Transaction",
|
||||
"New-WebServiceProxy",
|
||||
"Get-HotFix",
|
||||
"Test-Connection",
|
||||
"Enable-ComputerRestore",
|
||||
"Disable-ComputerRestore",
|
||||
"Checkpoint-Computer",
|
||||
"Get-ComputerRestorePoint",
|
||||
"Restart-Computer",
|
||||
"Stop-Computer",
|
||||
"Restore-Computer",
|
||||
"Add-Computer",
|
||||
"Remove-Computer",
|
||||
"Test-ComputerSecureChannel",
|
||||
"Reset-ComputerMachinePassword",
|
||||
"Rename-Computer",
|
||||
"Get-ControlPanelItem",
|
||||
"Show-ControlPanelItem",
|
||||
"Clear-Recyclebin",
|
||||
"Get-Clipboard",
|
||||
"Set-Clipboard")
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
@{
|
||||
GUID="A94C8C7E-9810-47C0-B8AF-65089C13A35A"
|
||||
Author="Microsoft Corporation"
|
||||
CompanyName="Microsoft Corporation"
|
||||
Copyright="© Microsoft Corporation. All rights reserved."
|
||||
ModuleVersion="3.0.0.0"
|
||||
PowerShellVersion="3.0"
|
||||
CLRVersion="4.0"
|
||||
AliasesToExport = @()
|
||||
FunctionsToExport = @()
|
||||
CmdletsToExport="Get-Acl", "Set-Acl", "Get-PfxCertificate", "Get-Credential", "Get-ExecutionPolicy", "Set-ExecutionPolicy", "Get-AuthenticodeSignature", "Set-AuthenticodeSignature", "ConvertFrom-SecureString", "ConvertTo-SecureString", "Get-CmsMessage", "Unprotect-CmsMessage", "Protect-CmsMessage" , "New-FileCatalog" , "Test-FileCatalog"
|
||||
NestedModules="Microsoft.PowerShell.Security.dll"
|
||||
HelpInfoURI = 'http://go.microsoft.com/fwlink/?linkid=390786'
|
||||
}
|
||||
@@ -0,0 +1,709 @@
|
||||
function Get-FileHash
|
||||
{
|
||||
[CmdletBinding(DefaultParameterSetName = "Path", HelpURI = "http://go.microsoft.com/fwlink/?LinkId=517145")]
|
||||
param(
|
||||
[Parameter(Mandatory, ParameterSetName="Path", Position = 0)]
|
||||
[System.String[]]
|
||||
$Path,
|
||||
|
||||
[Parameter(Mandatory, ParameterSetName="LiteralPath", ValueFromPipelineByPropertyName = $true)]
|
||||
[Alias("PSPath")]
|
||||
[System.String[]]
|
||||
$LiteralPath,
|
||||
|
||||
[Parameter(Mandatory, ParameterSetName="Stream")]
|
||||
[System.IO.Stream]
|
||||
$InputStream,
|
||||
|
||||
[ValidateSet("SHA1", "SHA256", "SHA384", "SHA512", "MACTripleDES", "MD5", "RIPEMD160")]
|
||||
[System.String]
|
||||
$Algorithm="SHA256"
|
||||
)
|
||||
|
||||
begin
|
||||
{
|
||||
# Construct the strongly-typed crypto object
|
||||
|
||||
# First see if it has a FIPS algorithm
|
||||
$hasherType = "System.Security.Cryptography.${Algorithm}CryptoServiceProvider" -as [Type]
|
||||
if ($hasherType)
|
||||
{
|
||||
$hasher = $hasherType::New()
|
||||
}
|
||||
else
|
||||
{
|
||||
# Check if the type is supported in the current system
|
||||
$algorithmType = "System.Security.Cryptography.${Algorithm}" -as [Type]
|
||||
if ($algorithmType)
|
||||
{
|
||||
if ($Algorithm -eq "MACTripleDES")
|
||||
{
|
||||
$hasher = $algorithmType::New()
|
||||
}
|
||||
else
|
||||
{
|
||||
$hasher = $algorithmType::Create()
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$errorId = "AlgorithmTypeNotSupported"
|
||||
$errorCategory = [System.Management.Automation.ErrorCategory]::InvalidArgument
|
||||
$errorMessage = [Microsoft.PowerShell.Commands.UtilityResources]::AlgorithmTypeNotSupported -f $Algorithm
|
||||
$exception = [System.InvalidOperationException]::New($errorMessage)
|
||||
$errorRecord = [System.Management.Automation.ErrorRecord]::New($exception, $errorId, $errorCategory, $null)
|
||||
$PSCmdlet.ThrowTerminatingError($errorRecord)
|
||||
}
|
||||
}
|
||||
|
||||
function GetStreamHash
|
||||
{
|
||||
param(
|
||||
[System.IO.Stream]
|
||||
$InputStream,
|
||||
|
||||
[System.String]
|
||||
$RelatedPath,
|
||||
|
||||
[System.Security.Cryptography.HashAlgorithm]
|
||||
$Hasher)
|
||||
|
||||
# Compute file-hash using the crypto object
|
||||
[Byte[]] $computedHash = $Hasher.ComputeHash($InputStream)
|
||||
[string] $hash = [BitConverter]::ToString($computedHash) -replace '-',''
|
||||
|
||||
if ($RelatedPath -eq $null)
|
||||
{
|
||||
$retVal = [PSCustomObject] @{
|
||||
Algorithm = $Algorithm.ToUpperInvariant()
|
||||
Hash = $hash
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$retVal = [PSCustomObject] @{
|
||||
Algorithm = $Algorithm.ToUpperInvariant()
|
||||
Hash = $hash
|
||||
Path = $RelatedPath
|
||||
}
|
||||
}
|
||||
$retVal.psobject.TypeNames.Insert(0, "Microsoft.Powershell.Utility.FileHash")
|
||||
$retVal
|
||||
}
|
||||
}
|
||||
|
||||
process
|
||||
{
|
||||
if($PSCmdlet.ParameterSetName -eq "Stream")
|
||||
{
|
||||
GetStreamHash -InputStream $InputStream -RelatedPath $null -Hasher $hasher
|
||||
}
|
||||
else
|
||||
{
|
||||
$pathsToProcess = @()
|
||||
if($PSCmdlet.ParameterSetName -eq "LiteralPath")
|
||||
{
|
||||
$pathsToProcess += Resolve-Path -LiteralPath $LiteralPath | Foreach-Object ProviderPath
|
||||
}
|
||||
if($PSCmdlet.ParameterSetName -eq "Path")
|
||||
{
|
||||
$pathsToProcess += Resolve-Path $Path | Foreach-Object ProviderPath
|
||||
}
|
||||
|
||||
foreach($filePath in $pathsToProcess)
|
||||
{
|
||||
if(Test-Path -LiteralPath $filePath -PathType Container)
|
||||
{
|
||||
continue
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
# Read the file specified in $FilePath as a Byte array
|
||||
[system.io.stream]$stream = [system.io.file]::OpenRead($filePath)
|
||||
GetStreamHash -InputStream $stream -RelatedPath $filePath -Hasher $hasher
|
||||
}
|
||||
catch [Exception]
|
||||
{
|
||||
$errorMessage = [Microsoft.PowerShell.Commands.UtilityResources]::FileReadError -f $FilePath, $_
|
||||
Write-Error -Message $errorMessage -Category ReadError -ErrorId "FileReadError" -TargetObject $FilePath
|
||||
return
|
||||
}
|
||||
finally
|
||||
{
|
||||
if($stream)
|
||||
{
|
||||
$stream.Dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<# This cmdlet is used to create a new temporary file in $env:temp #>
|
||||
function New-TemporaryFile
|
||||
{
|
||||
[CmdletBinding(
|
||||
HelpURI='http://go.microsoft.com/fwlink/?LinkId=526726',
|
||||
SupportsShouldProcess=$true)]
|
||||
[OutputType([System.IO.FileInfo])]
|
||||
Param()
|
||||
|
||||
Begin
|
||||
{
|
||||
try
|
||||
{
|
||||
if($PSCmdlet.ShouldProcess($env:TEMP))
|
||||
{
|
||||
$tempFilePath = [System.IO.Path]::GetTempFileName()
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
$errorRecord = [System.Management.Automation.ErrorRecord]::new($_.Exception,"NewTemporaryFileWriteError", "WriteError", $env:TEMP)
|
||||
Write-Error -ErrorRecord $errorRecord
|
||||
return
|
||||
}
|
||||
|
||||
if($tempFilePath)
|
||||
{
|
||||
Get-Item $tempFilePath
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<# This cmdlet is used to generate a new guid #>
|
||||
function New-Guid
|
||||
{
|
||||
[CmdletBinding(HelpURI='http://go.microsoft.com/fwlink/?LinkId=526920')]
|
||||
[OutputType([System.Guid])]
|
||||
Param()
|
||||
|
||||
Begin
|
||||
{
|
||||
[Guid]::NewGuid()
|
||||
}
|
||||
}
|
||||
|
||||
<############################################################################################
|
||||
# Format-Hex cmdlet helps in displaying the Hexadecimal equivalent of the input data.
|
||||
############################################################################################>
|
||||
function Format-Hex
|
||||
{
|
||||
[CmdletBinding(
|
||||
DefaultParameterSetName="Path",
|
||||
HelpUri="http://go.microsoft.com/fwlink/?LinkId=526919")]
|
||||
[Alias("fhx")]
|
||||
[OutputType("Microsoft.PowerShell.Commands.ByteCollection")]
|
||||
param
|
||||
(
|
||||
[Parameter (Mandatory=$true, Position=0, ParameterSetName="Path")]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string[]] $Path,
|
||||
|
||||
[Parameter (Mandatory=$true, ParameterSetName="LiteralPath")]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Alias("PSPath")]
|
||||
[string[]] $LiteralPath,
|
||||
|
||||
[Parameter(Mandatory=$true, ParameterSetName="ByInputObject", ValueFromPipeline=$true)]
|
||||
[Object] $InputObject,
|
||||
|
||||
[Parameter (ParameterSetName="ByInputObject")]
|
||||
[ValidateSet("Ascii", "UTF32", "UTF7", "UTF8", "BigEndianUnicode", "Unicode")]
|
||||
[string] $Encoding = "Ascii",
|
||||
|
||||
[Parameter(ParameterSetName="ByInputObject")]
|
||||
[switch]$Raw
|
||||
)
|
||||
|
||||
begin
|
||||
{
|
||||
$bufferSize = 16
|
||||
$inputStreamArray = [System.Collections.ArrayList]::New()
|
||||
<############################################################################################
|
||||
# The ConvertToHexadecimalHelper is a helper method used to fetch unicode bytes from the
|
||||
# input data and display the hexadecimial representaion of the of the input data in bytes.
|
||||
############################################################################################>
|
||||
function ConvertToHexadecimalHelper
|
||||
{
|
||||
param
|
||||
(
|
||||
[Byte[]] $inputBytes,
|
||||
[string] $path,
|
||||
[Uint32] $offset
|
||||
)
|
||||
|
||||
# This section is used to display the hexadecimal
|
||||
# representaion of the of the input data in bytes.
|
||||
if($inputBytes -ne $null)
|
||||
{
|
||||
$byteCollectionObject = [Microsoft.PowerShell.Commands.ByteCollection]::new($offset, $inputBytes, $path)
|
||||
Write-Output -InputObject $byteCollectionObject
|
||||
}
|
||||
}
|
||||
|
||||
<############################################################################################
|
||||
# The ProcessFileContent is a helper method used to fetch file contents in blocks and
|
||||
# process it to support displaying hexadecimal formating of the fetched content.
|
||||
############################################################################################>
|
||||
function ProcessFileContent
|
||||
{
|
||||
param
|
||||
(
|
||||
[string] $filePath,
|
||||
[boolean] $isLiteralPath
|
||||
)
|
||||
|
||||
if($isLiteralPath)
|
||||
{
|
||||
$resolvedPaths = Resolve-Path -LiteralPath $filePath
|
||||
}
|
||||
else
|
||||
{
|
||||
$resolvedPaths = Resolve-Path -Path $filePath
|
||||
}
|
||||
|
||||
# If Path resolution has failed then a corresponding non-terminating error is
|
||||
# written to the pipeline. We continue processing any remaining files.
|
||||
if($resolvedPaths -eq $null)
|
||||
{
|
||||
return
|
||||
}
|
||||
|
||||
if($resolvedPaths.Count -gt 1)
|
||||
{
|
||||
# write a non-terminating error message indicating that path specified is resolving to multiple file system paths.
|
||||
$errorMessage = [Microsoft.PowerShell.Commands.UtilityResources]::FormatHexResolvePathError -f $filePath
|
||||
Write-Error -Message $errorMessage -Category ([System.Management.Automation.ErrorCategory]::InvalidData) -ErrorId "FormatHexResolvePathError"
|
||||
}
|
||||
|
||||
$targetFilePath = $resolvedPaths.ProviderPath
|
||||
|
||||
|
||||
if($targetFilePath -ne $null)
|
||||
{
|
||||
$buffer = [byte[]]::new($bufferSize)
|
||||
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
$currentFileStream = [System.IO.File]::Open($targetFilePath, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read)
|
||||
}
|
||||
catch
|
||||
{
|
||||
# Failed to access the file. Write a non terminating error to the pipeline
|
||||
# and move on with the remaining files.
|
||||
$exception = $_.Exception
|
||||
if($null -ne $_.Exception -and
|
||||
$null -ne $_.Exception.InnerException)
|
||||
{
|
||||
$exception = $_.Exception.InnerException
|
||||
}
|
||||
|
||||
$errorRecord = [System.Management.Automation.ErrorRecord]::new($exception,"FormatHexFileAccessError", ([System.Management.Automation.ErrorCategory]::ReadError), $targetFilePath)
|
||||
$PSCmdlet.WriteError($errorRecord)
|
||||
}
|
||||
|
||||
if($null -ne $currentFileStream)
|
||||
{
|
||||
$srcStream = [System.IO.BinaryReader]::new($currentFileStream)
|
||||
$displayHeader = $true
|
||||
$offset = 0
|
||||
$blockCounter = 0
|
||||
while($numberOfBytesRead = $srcStream.Read($buffer, 0, $bufferSize))
|
||||
{
|
||||
# send only the bytes that have been read
|
||||
# if we send the whole buffer, we'll have extraneous bytes
|
||||
# at the end of an incomplete group of 16 bytes
|
||||
if ( $numberOfBytesRead -eq $bufferSize )
|
||||
{
|
||||
# under some circumstances if we don't copy the buffer
|
||||
# and the results are stored to a variable, the results are not
|
||||
# correct and one object replicated in all the output objects
|
||||
ConvertToHexadecimalHelper ($buffer.Clone()) $targetFilePath $offset
|
||||
}
|
||||
else
|
||||
{
|
||||
# handle the case of the partial (and probably last) buffer
|
||||
$bytesReadBuffer = [byte[]]::New($numberOfBytesRead)
|
||||
[Array]::Copy($buffer,0, $bytesReadBuffer,0,$numberOfBytesRead)
|
||||
ConvertToHexadecimalHelper $bytesReadBuffer $targetFilePath $offset
|
||||
}
|
||||
$displayHeader = $false
|
||||
$blockCounter++;
|
||||
|
||||
# Updating the offset value.
|
||||
$offset = $blockCounter*0x10
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
If($null -ne $currentFileStream)
|
||||
{
|
||||
$currentFileStream.Dispose()
|
||||
}
|
||||
If($null -ne $srcStream)
|
||||
{
|
||||
$srcStream.Dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
process
|
||||
{
|
||||
switch($PSCmdlet.ParameterSetName)
|
||||
{
|
||||
"Path"
|
||||
{
|
||||
ProcessFileContent $Path $false
|
||||
}
|
||||
"LiteralPath"
|
||||
{
|
||||
ProcessFileContent $LiteralPath $true
|
||||
}
|
||||
"ByInputObject"
|
||||
{
|
||||
# If it's an actual byte array, then we directly use it for hexadecimal formatting.
|
||||
if($InputObject -is [Byte[]])
|
||||
{
|
||||
ConvertToHexadecimalHelper $InputObject $null
|
||||
return
|
||||
}
|
||||
# if it's a single byte, we'll assume streaming
|
||||
elseif($InputObject -is [byte])
|
||||
{
|
||||
$null = $inputStreamArray.Add($InputObject)
|
||||
}
|
||||
# If the input data is of string type then directly get bytes out of it.
|
||||
elseif($InputObject -is [string])
|
||||
{
|
||||
# The ValidateSet arribute on the Encoding paramter makes sure that only
|
||||
# valid values (supported on all paltforms where Format-Hex is avaliable)
|
||||
# are allowed through user input.
|
||||
$inputBytes = [Text.Encoding]::$Encoding.GetBytes($InputObject)
|
||||
ConvertToHexadecimalHelper $inputBytes $null
|
||||
return
|
||||
}
|
||||
elseif($InputObject -is [System.IO.FileSystemInfo])
|
||||
{
|
||||
# If file path is provided as an input, use the file contents to show the hexadecimal format.
|
||||
$filePath = ([System.IO.FileSystemInfo]$InputObject).FullName
|
||||
ProcessFileContent $filePath $false
|
||||
return
|
||||
}
|
||||
elseif($InputObject -is [int64])
|
||||
{
|
||||
$inputBytes = [BitConverter]::GetBytes($InputObject)
|
||||
$null = $inputStreamArray.AddRange($inputBytes)
|
||||
}
|
||||
elseif($InputObject -is [int64[]])
|
||||
{
|
||||
foreach($i64 in $InputObject)
|
||||
{
|
||||
$inputBytes = [BitConverter]::GetBytes($i64)
|
||||
$null = $inputStreamArray.AddRange($inputBytes)
|
||||
}
|
||||
}
|
||||
elseif($InputObject -is [int])
|
||||
{
|
||||
# If we get what appears as ints, it may not be what the user really wants.
|
||||
# for example, if the user types a small set of numbers just to get their
|
||||
# character representations, as follows:
|
||||
#
|
||||
# 170..180 | format-hex
|
||||
# Path:
|
||||
# 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
|
||||
#00000000 AA AB AC AD AE AF B0 B1 B2 B3 B4 ª«¬®¯°±²³´
|
||||
#
|
||||
# any integer padding is likely to be more confusing than this
|
||||
# fairly compact representation.
|
||||
#
|
||||
# However, some might like to see the results with the raw data,
|
||||
# -Raw exists to provide that behavior:
|
||||
# PS# 170..180 | format-hex -Raw
|
||||
#
|
||||
# Path:
|
||||
#
|
||||
# 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
|
||||
#
|
||||
# 00000000 AA 00 00 00 AB 00 00 00 AC 00 00 00 AD 00 00 00 ª...«...¬......
|
||||
# 00000010 AE 00 00 00 AF 00 00 00 B0 00 00 00 B1 00 00 00 ®...¯...°...±...
|
||||
# 00000020 B2 00 00 00 B3 00 00 00 B4 00 00 00 ²...³...´...
|
||||
#
|
||||
# this provides a representation of the piped numbers which includes all
|
||||
# of the bytes which are in an int32
|
||||
if ( $Raw )
|
||||
{
|
||||
$inputBytes = [BitConverter]::GetBytes($InputObject)
|
||||
$null = $inputStreamArray.AddRange($inputBytes)
|
||||
}
|
||||
else
|
||||
{
|
||||
# first determine whether we can represent this as a byte
|
||||
$possibleByte = $InputObject -as [byte]
|
||||
# first determine whether we can represent this as a int16
|
||||
$possibleInt16 = $InputObject -as [int16]
|
||||
if ( $possibleByte -ne $null )
|
||||
{
|
||||
$null = $inputStreamArray.Add($possibleByte)
|
||||
}
|
||||
elseif ( $possibleint16 -ne $null )
|
||||
{
|
||||
$inputBytes = [BitConverter]::GetBytes($possibleInt16)
|
||||
$null = $inputStreamArray.AddRange($inputBytes)
|
||||
}
|
||||
else
|
||||
{
|
||||
# now int
|
||||
$inputBytes = [BitConverter]::GetBytes($InputObject)
|
||||
$null = $inputStreamArray.AddRange($inputBytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
# Otherwise, write a non-terminating error message indicating that input object type is not supported.
|
||||
$errorMessage = [Microsoft.PowerShell.Commands.UtilityResources]::FormatHexTypeNotSupported -f $InputObject.GetType()
|
||||
Write-Error -Message $errorMessage -Category ([System.Management.Automation.ErrorCategory]::ParserError) -ErrorId "FormatHexFailureTypeNotSupported"
|
||||
}
|
||||
# Handle streaming case here
|
||||
# during this process we may not have enough characters to create a ByteCollection
|
||||
# if we do, create as many ByteCollections as necessary, each being 16 bytes in length
|
||||
if ( $inputStreamArray.Count -ge $bufferSize )
|
||||
{
|
||||
$rowCount = [math]::Floor($inputStreamArray.Count/$bufferSize)
|
||||
$arrayLength = $bufferSize * $rowCount
|
||||
for($i = 0; $i -lt $rowCount; $i++)
|
||||
{
|
||||
$rowOffset = $i * $bufferSize
|
||||
ConvertToHexadecimalHelper -inputBytes $inputStreamArray.GetRange($rowOffset, $bufferSize) -path ' ' -offset $offset
|
||||
$offset += $bufferSize
|
||||
}
|
||||
# We use RemoveRange because of the pathological case of having
|
||||
# streamed combination of bytes, int16, int32, int64 which are greater
|
||||
# than 16 bytes. Consider the case:
|
||||
# $i = [int16]::MaxValue + 3
|
||||
# $i64=[int64]::MaxValue -5
|
||||
# .{ $i;$i;$i;$i64 } | format-hex
|
||||
# which create an arraylist 20 bytes
|
||||
# we need to remove only the bytes from the array which we emitted
|
||||
$inputStreamArray.RemoveRange(0,$arrayLength)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
{
|
||||
# now manage any left over bytes in the $inputStreamArray
|
||||
if ( $PSCmdlet.ParameterSetName -eq "ByInputObject" )
|
||||
{
|
||||
ConvertToHexadecimalHelper $inputStreamArray $null -path ' ' -offset $offset
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
## Imports a PowerShell Data File - a PowerShell hashtable defined in
|
||||
## a file (such as a Module manifest, session configuration file)
|
||||
function Import-PowerShellDataFile
|
||||
{
|
||||
[CmdletBinding(DefaultParameterSetName = "ByPath", HelpUri = "http://go.microsoft.com/fwlink/?LinkID=623621")]
|
||||
[OutputType("System.Collections.Hashtable")]
|
||||
param(
|
||||
[Parameter(ParameterSetName = "ByPath", Position = 0)]
|
||||
[String[]] $Path,
|
||||
|
||||
[Parameter(ParameterSetName = "ByLiteralPath", ValueFromPipelineByPropertyName = $true)]
|
||||
[Alias("PSPath")]
|
||||
[String[]] $LiteralPath
|
||||
)
|
||||
|
||||
begin
|
||||
{
|
||||
function ThrowInvalidDataFile
|
||||
{
|
||||
param($resolvedPath, $extraError)
|
||||
|
||||
$errorId = "CouldNotParseAsPowerShellDataFile$extraError"
|
||||
$errorCategory = [System.Management.Automation.ErrorCategory]::InvalidData
|
||||
$errorMessage = [Microsoft.PowerShell.Commands.UtilityResources]::CouldNotParseAsPowerShellDataFile -f $resolvedPath
|
||||
$exception = [System.InvalidOperationException]::New($errorMessage)
|
||||
$errorRecord = [System.Management.Automation.ErrorRecord]::New($exception, $errorId, $errorCategory, $null)
|
||||
$PSCmdlet.WriteError($errorRecord)
|
||||
}
|
||||
}
|
||||
|
||||
process
|
||||
{
|
||||
foreach($resolvedPath in (Resolve-Path @PSBoundParameters))
|
||||
{
|
||||
$parseErrors = $null
|
||||
$ast = [System.Management.Automation.Language.Parser]::ParseFile(($resolvedPath.ProviderPath), [ref] $null, [ref] $parseErrors)
|
||||
if ($parseErrors.Length -gt 0)
|
||||
{
|
||||
ThrowInvalidDataFile $resolvedPath
|
||||
}
|
||||
else
|
||||
{
|
||||
$data = $ast.Find( { $args[0] -is [System.Management.Automation.Language.HashtableAst] }, $false )
|
||||
if($data)
|
||||
{
|
||||
$data.SafeGetValue()
|
||||
}
|
||||
else
|
||||
{
|
||||
ThrowInvalidDataFile $resolvedPath "NoHashtableRoot"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
## Converts a SDDL string into an object-based representation of a security
|
||||
## descriptor
|
||||
function ConvertFrom-SddlString
|
||||
{
|
||||
[CmdletBinding(HelpUri = "http://go.microsoft.com/fwlink/?LinkId=623636")]
|
||||
param(
|
||||
## The string representing the security descriptor in SDDL syntax
|
||||
[Parameter(Mandatory, Position = 0)]
|
||||
[String] $Sddl,
|
||||
|
||||
## The type of rights that this SDDL string represents, if any.
|
||||
[Parameter()]
|
||||
[ValidateSet(
|
||||
"FileSystemRights", "RegistryRights", "ActiveDirectoryRights",
|
||||
"MutexRights", "SemaphoreRights", "CryptoKeyRights",
|
||||
"EventWaitHandleRights")]
|
||||
$Type
|
||||
)
|
||||
|
||||
## Translates a SID into a NT Account
|
||||
function ConvertTo-NtAccount
|
||||
{
|
||||
param($Sid)
|
||||
|
||||
if($Sid)
|
||||
{
|
||||
$securityIdentifier = [System.Security.Principal.SecurityIdentifier] $Sid
|
||||
|
||||
try
|
||||
{
|
||||
$ntAccount = $securityIdentifier.Translate([System.Security.Principal.NTAccount]).ToString()
|
||||
}
|
||||
catch{}
|
||||
|
||||
$ntAccount
|
||||
}
|
||||
}
|
||||
|
||||
## Gets the access rights that apply to an access mask, preferring right types
|
||||
## of 'Type' if specified.
|
||||
function Get-AccessRights
|
||||
{
|
||||
param($AccessMask, $Type)
|
||||
|
||||
## All the types of access rights understood by .NET
|
||||
$rightTypes = [Ordered] @{
|
||||
"FileSystemRights" = [System.Security.AccessControl.FileSystemRights]
|
||||
"RegistryRights" = [System.Security.AccessControl.RegistryRights]
|
||||
"ActiveDirectoryRights" = [System.DirectoryServices.ActiveDirectoryRights]
|
||||
"MutexRights" = [System.Security.AccessControl.MutexRights]
|
||||
"SemaphoreRights" = [System.Security.AccessControl.SemaphoreRights]
|
||||
"CryptoKeyRights" = [System.Security.AccessControl.CryptoKeyRights]
|
||||
"EventWaitHandleRights" = [System.Security.AccessControl.EventWaitHandleRights]
|
||||
}
|
||||
$typesToExamine = $rightTypes.Values
|
||||
|
||||
## If they know the access mask represents a certain type, prefer its names
|
||||
## (i.e.: CreateLink for the registry over CreateDirectories for the filesystem)
|
||||
if($Type)
|
||||
{
|
||||
$typesToExamine = @($rightTypes[$Type]) + $typesToExamine
|
||||
}
|
||||
|
||||
|
||||
## Stores the access types we've found that apply
|
||||
$foundAccess = @()
|
||||
|
||||
## Store the access types we've already seen, so that we don't report access
|
||||
## flags that are essentially duplicate. Many of the access values in the different
|
||||
## enumerations have the same value but with different names.
|
||||
$foundValues = @{}
|
||||
|
||||
## Go through the entries in the different right types, and see if they apply to the
|
||||
## provided access mask. If they do, then add that to the result.
|
||||
foreach($rightType in $typesToExamine)
|
||||
{
|
||||
foreach($accessFlag in [Enum]::GetNames($rightType))
|
||||
{
|
||||
$longKeyValue = [long] $rightType::$accessFlag
|
||||
if(-not $foundValues.ContainsKey($longKeyValue))
|
||||
{
|
||||
$foundValues[$longKeyValue] = $true
|
||||
if(($AccessMask -band $longKeyValue) -eq ($longKeyValue))
|
||||
{
|
||||
$foundAccess += $accessFlag
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$foundAccess | Sort-Object
|
||||
}
|
||||
|
||||
## Converts an ACE into a string representation
|
||||
function ConvertTo-AceString
|
||||
{
|
||||
param(
|
||||
[Parameter(ValueFromPipeline)]
|
||||
$Ace,
|
||||
$Type
|
||||
)
|
||||
|
||||
process
|
||||
{
|
||||
foreach($aceEntry in $Ace)
|
||||
{
|
||||
$AceString = (ConvertTo-NtAccount $aceEntry.SecurityIdentifier) + ": " + $aceEntry.AceQualifier
|
||||
if($aceEntry.AceFlags -ne "None")
|
||||
{
|
||||
$AceString += " " + $aceEntry.AceFlags
|
||||
}
|
||||
|
||||
if($aceEntry.AccessMask)
|
||||
{
|
||||
$foundAccess = Get-AccessRights $aceEntry.AccessMask $Type
|
||||
|
||||
if($foundAccess)
|
||||
{
|
||||
$AceString += " ({0})" -f ($foundAccess -join ", ")
|
||||
}
|
||||
}
|
||||
|
||||
$AceString
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$rawSecurityDescriptor = [Security.AccessControl.CommonSecurityDescriptor]::new($false,$false,$Sddl)
|
||||
|
||||
$owner = ConvertTo-NtAccount $rawSecurityDescriptor.Owner
|
||||
$group = ConvertTo-NtAccount $rawSecurityDescriptor.Group
|
||||
$discretionaryAcl = ConvertTo-AceString $rawSecurityDescriptor.DiscretionaryAcl $Type
|
||||
$systemAcl = ConvertTo-AceString $rawSecurityDescriptor.SystemAcl $Type
|
||||
|
||||
[PSCustomObject] @{
|
||||
Owner = $owner
|
||||
Group = $group
|
||||
DiscretionaryAcl = @($discretionaryAcl)
|
||||
SystemAcl = @($systemAcl)
|
||||
RawDescriptor = $rawSecurityDescriptor
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
@{
|
||||
GUID="766204A6-330E-4263-A7AB-46C87AFC366C"
|
||||
Author="Microsoft Corporation"
|
||||
CompanyName="Microsoft Corporation"
|
||||
Copyright="© Microsoft Corporation. All rights reserved."
|
||||
ModuleVersion="3.0.0.0"
|
||||
PowerShellVersion="3.0"
|
||||
CLRVersion="4.0"
|
||||
AliasesToExport = @()
|
||||
FunctionsToExport = @()
|
||||
CmdletsToExport="Disable-WSManCredSSP", "Enable-WSManCredSSP", "Get-WSManCredSSP", "Set-WSManQuickConfig", "Test-WSMan", "Invoke-WSManAction", "Connect-WSMan", "Disconnect-WSMan", "Get-WSManInstance", "Set-WSManInstance", "Remove-WSManInstance", "New-WSManInstance", "New-WSManSessionOption"
|
||||
NestedModules="Microsoft.WSMan.Management.dll"
|
||||
FormatsToProcess="WSMan.format.ps1xml"
|
||||
HelpInfoURI = 'http://go.microsoft.com/fwlink/?linkid=390788'
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,202 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Configuration>
|
||||
<ViewDefinitions>
|
||||
<View>
|
||||
<Name>PSRepositoryItemInfo</Name>
|
||||
<ViewSelectedBy>
|
||||
<TypeName>Microsoft.PowerShell.Commands.PSRepositoryItemInfo</TypeName>
|
||||
</ViewSelectedBy>
|
||||
<TableControl>
|
||||
<TableHeaders>
|
||||
<TableColumnHeader>
|
||||
<Width>10</Width>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Width>35</Width>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Width>10</Width>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Width>20</Width>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader/>
|
||||
</TableHeaders>
|
||||
<TableRowEntries>
|
||||
<TableRowEntry>
|
||||
<TableColumnItems>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Version</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Name</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Type</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Repository</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Description</PropertyName>
|
||||
</TableColumnItem>
|
||||
</TableColumnItems>
|
||||
</TableRowEntry>
|
||||
</TableRowEntries>
|
||||
</TableControl>
|
||||
</View>
|
||||
<View>
|
||||
<Name>PSRepository</Name>
|
||||
<ViewSelectedBy>
|
||||
<TypeName>Microsoft.PowerShell.Commands.PSRepository</TypeName>
|
||||
</ViewSelectedBy>
|
||||
<TableControl>
|
||||
<TableHeaders>
|
||||
<TableColumnHeader>
|
||||
<Width>25</Width>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Width>25</Width>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Width>20</Width>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader/>
|
||||
</TableHeaders>
|
||||
<TableRowEntries>
|
||||
<TableRowEntry>
|
||||
<TableColumnItems>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Name</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>PackageManagementProvider</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>InstallationPolicy</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>SourceLocation</PropertyName>
|
||||
</TableColumnItem>
|
||||
</TableColumnItems>
|
||||
</TableRowEntry>
|
||||
</TableRowEntries>
|
||||
</TableControl>
|
||||
</View>
|
||||
<View>
|
||||
<Name>PSScriptInfo</Name>
|
||||
<ViewSelectedBy>
|
||||
<TypeName>Microsoft.PowerShell.Commands.PSScriptInfo</TypeName>
|
||||
</ViewSelectedBy>
|
||||
<TableControl>
|
||||
<TableHeaders>
|
||||
<TableColumnHeader>
|
||||
<Width>10</Width>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Width>25</Width>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Width>20</Width>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader/>
|
||||
</TableHeaders>
|
||||
<TableRowEntries>
|
||||
<TableRowEntry>
|
||||
<TableColumnItems>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Version</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Name</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Author</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Description</PropertyName>
|
||||
</TableColumnItem>
|
||||
</TableColumnItems>
|
||||
</TableRowEntry>
|
||||
</TableRowEntries>
|
||||
</TableControl>
|
||||
</View>
|
||||
<View>
|
||||
<Name>PSGetDscResourceInfo</Name>
|
||||
<ViewSelectedBy>
|
||||
<TypeName>Microsoft.PowerShell.Commands.PSGetCommandInfo</TypeName>
|
||||
<TypeName>Microsoft.PowerShell.Commands.PSGetDscResourceInfo</TypeName>
|
||||
</ViewSelectedBy>
|
||||
<TableControl>
|
||||
<TableHeaders>
|
||||
<TableColumnHeader>
|
||||
<Width>35</Width>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Width>10</Width>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Width>35</Width>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader/>
|
||||
</TableHeaders>
|
||||
<TableRowEntries>
|
||||
<TableRowEntry>
|
||||
<TableColumnItems>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Name</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Version</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>ModuleName</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Repository</PropertyName>
|
||||
</TableColumnItem>
|
||||
</TableColumnItems>
|
||||
</TableRowEntry>
|
||||
</TableRowEntries>
|
||||
</TableControl>
|
||||
</View>
|
||||
<View>
|
||||
<Name>PSGetRoleCapabilityInfo</Name>
|
||||
<ViewSelectedBy>
|
||||
<TypeName>Microsoft.PowerShell.Commands.PSGetRoleCapabilityInfo</TypeName>
|
||||
</ViewSelectedBy>
|
||||
<TableControl>
|
||||
<TableHeaders>
|
||||
<TableColumnHeader>
|
||||
<Width>35</Width>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Width>10</Width>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Width>35</Width>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader/>
|
||||
</TableHeaders>
|
||||
<TableRowEntries>
|
||||
<TableRowEntry>
|
||||
<TableColumnItems>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Name</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Version</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>ModuleName</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Repository</PropertyName>
|
||||
</TableColumnItem>
|
||||
</TableColumnItems>
|
||||
</TableRowEntry>
|
||||
</TableRowEntries>
|
||||
</TableControl>
|
||||
</View>
|
||||
</ViewDefinitions>
|
||||
</Configuration>
|
||||
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large.
Load diff
File renamed without changes.
@@ -3,8 +3,6 @@
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
--********************************************************************/
|
||||
|
||||
#if CORECLR
|
||||
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
@@ -1679,5 +1677,3 @@ namespace Microsoft.PowerShell.CoreCLR
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -12,8 +12,6 @@ using System.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.Win32;
|
||||
using System.Management.Automation.Remoting;
|
||||
|
||||
#if CORECLR
|
||||
|
||||
#pragma warning disable 1591, 1572, 1571, 1573, 1587, 1570, 0067
|
||||
|
||||
#region CLR_STUBS
|
||||
@@ -1874,5 +1872,3 @@ namespace System
|
||||
#pragma warning restore 1591, 1572, 1571, 1573, 1587, 1570, 0067
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -17,7 +17,7 @@ namespace ConsoleApplication
|
||||
var outputPath = "../TypeCatalogGen/powershell.inc";
|
||||
|
||||
// Get a context for our top level project
|
||||
var context = ProjectContext.Create("../Microsoft.PowerShell.Linux.Host", NuGetFramework.Parse("netstandardapp1.5"));
|
||||
var context = ProjectContext.Create("../Microsoft.PowerShell.Host", NuGetFramework.Parse("netstandardapp1.5"));
|
||||
|
||||
System.IO.File.WriteAllLines(outputPath,
|
||||
// Get the target for the current runtime
|
||||
|
||||
@@ -13,5 +13,14 @@
|
||||
"netstandardapp1.5": {
|
||||
"imports": [ "dnxcore50", "portable-net45+win8" ]
|
||||
}
|
||||
},
|
||||
|
||||
"runtimes": {
|
||||
"ubuntu.14.04-x64": { },
|
||||
"centos.7.1-x64": { },
|
||||
"win7-x64": { },
|
||||
"win10-x64": { },
|
||||
"osx.10.10-x64": { },
|
||||
"osx.10.11-x64": { }
|
||||
}
|
||||
}
|
||||
Submodule src/libpsl-native deleted from 4bb241ad11.
@@ -0,0 +1,12 @@
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
CMakeScripts
|
||||
Makefile
|
||||
cmake_install.cmake
|
||||
install_manifest.txt
|
||||
CTestTestfile.cmake
|
||||
Testing/
|
||||
test/psl-native-test
|
||||
src/libpsl-native.so
|
||||
src/libpsl-native.dylib
|
||||
test/native-tests.xml
|
||||
@@ -0,0 +1,10 @@
|
||||
cmake_minimum_required(VERSION 2.8.4)
|
||||
project(PSL-NATIVE)
|
||||
|
||||
add_compile_options(-std=c++11 -Wall -Werror)
|
||||
set(LIBRARY_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/../Microsoft.PowerShell.Host")
|
||||
|
||||
# test in BUILD_DIR
|
||||
enable_testing()
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(test)
|
||||
@@ -0,0 +1,56 @@
|
||||
# libpsl-native
|
||||
|
||||
This library provides functionality missing from .NET Core via system calls,
|
||||
that are called from from the `CorePsPlatform.cs` file of PowerShell. The
|
||||
method to do this is a Platform Invoke, which is C#'s Foreign Function
|
||||
Interface to C code (and C++ by way of `extern C`).
|
||||
|
||||
## Build
|
||||
|
||||
[CMake][] is used to build the project, which results in a `libpsl-native.so`
|
||||
library on Linux, and `libpsl-native.dylib` on OS X.
|
||||
|
||||
```sh
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug .
|
||||
make -j
|
||||
```
|
||||
|
||||
[CMake]: https://cmake.org/cmake/help/v2.8.12/cmake.html
|
||||
|
||||
## Test
|
||||
|
||||
The [Google Test][] framework is used for unit tests.
|
||||
|
||||
Use either `make test` or `ctest --verbose` for more output.
|
||||
|
||||
[Google Test]: https://github.com/google/googletest/tree/release-1.7.0
|
||||
|
||||
## Notes
|
||||
|
||||
Marshalling data from native to managed code is much easier on Linux than it is
|
||||
on Windows. For instance, to return a string, you simply return a copy of it on
|
||||
the heap. Since only one memory allocator is used on Linux, the .NET runtime
|
||||
has no problem later freeing the buffer. Additionally, .NET presumes that the
|
||||
codepage "Ansi" on Linux is always UTF-8. So just marshal the string as
|
||||
`UnmanagedType.LPStr`.
|
||||
|
||||
### C# (Managed)
|
||||
|
||||
```c#
|
||||
[DllImport("libpsl-native", CharSet = CharSet.Ansi)]
|
||||
[return: MarshalAs(UnmanagedType.LPStr)]
|
||||
internal static extern string GetSomeString();
|
||||
```
|
||||
|
||||
### C (Native)
|
||||
|
||||
```c
|
||||
char *GetSomeString()
|
||||
{
|
||||
return strdup("some string");
|
||||
}
|
||||
```
|
||||
|
||||
The CoreFX team has an excellent guide for [UNIX Interop][].
|
||||
|
||||
[UNIX Interop]: https://github.com/dotnet/corefx/blob/master/Documentation/coding-guidelines/interop-guidelines.md#unix-shims
|
||||
@@ -0,0 +1,14 @@
|
||||
add_library(psl-native SHARED
|
||||
getcurrentprocessorid.cpp
|
||||
getusername.cpp
|
||||
getcomputername.cpp
|
||||
getlinkcount.cpp
|
||||
getfullyqualifiedname.cpp
|
||||
issymlink.cpp
|
||||
isexecutable.cpp
|
||||
setdate.cpp
|
||||
createhardlink.cpp
|
||||
createsymlink.cpp
|
||||
followsymlink.cpp)
|
||||
|
||||
target_include_directories(psl-native PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
@@ -0,0 +1,115 @@
|
||||
//! @file createsymlink.cpp
|
||||
//! @author George FLeming <v-geflem@microsoft.com>
|
||||
//! @brief create new hard link
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
#include "createhardlink.h"
|
||||
|
||||
//! @brief Createhardlink create new symbolic link
|
||||
//!
|
||||
//! Createhardlink
|
||||
//!
|
||||
//! @param[in] link
|
||||
//! @parblock
|
||||
//! A pointer to the buffer that contains the symbolic link to create
|
||||
//!
|
||||
//! char* is marshaled as an LPStr, which on Linux is UTF-8.
|
||||
//! @endparblock
|
||||
//!
|
||||
//! @param[in] target
|
||||
//! @parblock
|
||||
//! A pointer to the buffer that contains the existing file
|
||||
//!
|
||||
//! char* is marshaled as an LPStr, which on Linux is UTF-8.
|
||||
//! @endparblock
|
||||
//!
|
||||
//! @exception errno Passes these errors via errno to GetLastError:
|
||||
//! - ERROR_INVALID_PARAMETER: parameter is not valid
|
||||
//! - ERROR_FILE_NOT_FOUND: file does not exist
|
||||
//! - ERROR_ACCESS_DENIED: access is denied
|
||||
//! - ERROR_FILE_NOT_FOUND: the system cannot find the file specified
|
||||
//! - ERROR_INVALID_ADDRESS: attempt to access invalid address
|
||||
//! - ERROR_TOO_MANY_LINK: max number of hard links has been exceeded
|
||||
//! - ERROR_GEN_FAILURE: device attached to the system is not functioning
|
||||
//! - ERROR_NO_SUCH_USER: there was no corresponding entry in the utmp-file
|
||||
//! - ERROR_INVALID_NAME: filename, directory name, or volume label syntax is incorrect
|
||||
//! - ERROR_BUFFER_OVERFLOW: file name is too long
|
||||
//! - ERROR_INVALID_FUNCTION: incorrect function
|
||||
//! - ERROR_BAD_PATH_NAME: pathname is too long, or contains invalid characters
|
||||
//!
|
||||
//! @retval 1 if creation is successful
|
||||
//! @retval 0 if createion failed
|
||||
//!
|
||||
|
||||
int32_t CreateHardLink(const char *newlink, const char *target)
|
||||
{
|
||||
errno = 0;
|
||||
|
||||
// Check parameters
|
||||
if (!newlink || !target)
|
||||
{
|
||||
errno = ERROR_INVALID_PARAMETER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int returnCode = link(target, newlink);
|
||||
|
||||
if (returnCode == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch(errno)
|
||||
{
|
||||
case EACCES:
|
||||
errno = ERROR_ACCESS_DENIED;
|
||||
break;
|
||||
case EDQUOT:
|
||||
errno = ERROR_DISK_FULL;
|
||||
break;
|
||||
case EEXIST:
|
||||
errno = ERROR_FILE_EXISTS;
|
||||
break;
|
||||
case EFAULT:
|
||||
errno = ERROR_INVALID_ADDRESS;
|
||||
break;
|
||||
case EIO:
|
||||
errno = ERROR_GEN_FAILURE;
|
||||
break;
|
||||
case ELOOP:
|
||||
errno = ERROR_TOO_MANY_LINKS;
|
||||
break;
|
||||
case EMLINK:
|
||||
errno = ERROR_TOO_MANY_LINKS;
|
||||
break;
|
||||
case ENAMETOOLONG:
|
||||
errno = ERROR_BAD_PATH_NAME;
|
||||
break;
|
||||
case ENOENT:
|
||||
errno = ERROR_FILE_NOT_FOUND;
|
||||
break;
|
||||
case ENOMEM:
|
||||
errno = ERROR_OUTOFMEMORY;
|
||||
break;
|
||||
case ENOTDIR:
|
||||
errno = ERROR_INVALID_NAME;
|
||||
break;
|
||||
case ENOSPC:
|
||||
errno = ERROR_DISK_FULL;
|
||||
break;
|
||||
case EPERM:
|
||||
errno = ERROR_ACCESS_DENIED;
|
||||
break;
|
||||
case EROFS:
|
||||
errno = ERROR_ACCESS_DENIED;
|
||||
break;
|
||||
case EXDEV:
|
||||
errno = ERROR_GEN_FAILURE;
|
||||
break;
|
||||
default:
|
||||
errno = ERROR_INVALID_FUNCTION;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
int32_t CreateHardLink(const char *link, const char *target);
|
||||
|
||||
PAL_END_EXTERNC
|
||||
@@ -0,0 +1,106 @@
|
||||
//! @file createsymlink.cpp
|
||||
//! @author George FLeming <v-geflem@microsoft.com>
|
||||
//! @brief create new symbolic link
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
#include "createsymlink.h"
|
||||
|
||||
//! @brief Createsymlink create new symbolic link
|
||||
//!
|
||||
//! Createsymlink
|
||||
//!
|
||||
//! @param[in] link
|
||||
//! @parblock
|
||||
//! A pointer to the buffer that contains the symbolic link to create
|
||||
//!
|
||||
//! char* is marshaled as an LPStr, which on Linux is UTF-8.
|
||||
//! @endparblock
|
||||
//!
|
||||
//! @param[in] target
|
||||
//! @parblock
|
||||
//! A pointer to the buffer that contains the existing file
|
||||
//!
|
||||
//! char* is marshaled as an LPStr, which on Linux is UTF-8.
|
||||
//! @endparblock
|
||||
//!
|
||||
//! @exception errno Passes these errors via errno to GetLastError:
|
||||
//! - ERROR_INVALID_PARAMETER: parameter is not valid
|
||||
//! - ERROR_FILE_NOT_FOUND: file does not exist
|
||||
//! - ERROR_ACCESS_DENIED: access is denied
|
||||
//! - ERROR_FILE_NOT_FOUND: the system cannot find the file specified
|
||||
//! - ERROR_INVALID_ADDRESS: attempt to access invalid address
|
||||
//! - ERROR_STOPPED_ON_SYMLINK: the operation stopped after reaching a symbolic link
|
||||
//! - ERROR_GEN_FAILURE: device attached to the system is not functioning
|
||||
//! - ERROR_NO_SUCH_USER: there was no corresponding entry in the utmp-file
|
||||
//! - ERROR_INVALID_NAME: filename, directory name, or volume label syntax is incorrect
|
||||
//! - ERROR_BUFFER_OVERFLOW: file name is too long
|
||||
//! - ERROR_INVALID_FUNCTION: incorrect function
|
||||
//! - ERROR_BAD_PATH_NAME: pathname is too long, or contains invalid characters
|
||||
//!
|
||||
//! @retval 1 if creation is successful
|
||||
//! @retval 0 if createion failed
|
||||
//!
|
||||
|
||||
int32_t CreateSymLink(const char *link, const char *target)
|
||||
{
|
||||
errno = 0;
|
||||
|
||||
// Check parameters
|
||||
if (!link || !target)
|
||||
{
|
||||
errno = ERROR_INVALID_PARAMETER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int returnCode = symlink(target, link);
|
||||
|
||||
if (returnCode == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch(errno)
|
||||
{
|
||||
case EACCES:
|
||||
errno = ERROR_ACCESS_DENIED;
|
||||
break;
|
||||
case EDQUOT:
|
||||
errno = ERROR_DISK_FULL;
|
||||
break;
|
||||
case EEXIST:
|
||||
errno = ERROR_FILE_EXISTS;
|
||||
break;
|
||||
case EFAULT:
|
||||
errno = ERROR_INVALID_ADDRESS;
|
||||
break;
|
||||
case EIO:
|
||||
errno = ERROR_GEN_FAILURE;
|
||||
break;
|
||||
case ELOOP:
|
||||
errno = ERROR_STOPPED_ON_SYMLINK;
|
||||
break;
|
||||
case ENAMETOOLONG:
|
||||
errno = ERROR_BAD_PATH_NAME;
|
||||
break;
|
||||
case ENOENT:
|
||||
errno = ERROR_FILE_NOT_FOUND;
|
||||
break;
|
||||
case ENOMEM:
|
||||
errno = ERROR_OUTOFMEMORY;
|
||||
break;
|
||||
case ENOTDIR:
|
||||
errno = ERROR_INVALID_NAME;
|
||||
break;
|
||||
case ENOSPC:
|
||||
errno = ERROR_DISK_FULL;
|
||||
break;
|
||||
case EPERM:
|
||||
errno = ERROR_GEN_FAILURE;
|
||||
break;
|
||||
default:
|
||||
errno = ERROR_INVALID_FUNCTION;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
int32_t CreateSymLink(const char *link, const char *target);
|
||||
|
||||
PAL_END_EXTERNC
|
||||
@@ -0,0 +1,90 @@
|
||||
//! @file followSymLink.cpp
|
||||
//! @author George FLeming <v-geflem@microsoft.com>
|
||||
//! @brief returns whether a path is a symbolic link
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include "followsymlink.h"
|
||||
|
||||
//! @brief Followsymlink determines target path of a sym link
|
||||
//!
|
||||
//! Followsymlink
|
||||
//!
|
||||
//! @param[in] fileName
|
||||
//! @parblock
|
||||
//! A pointer to the buffer that contains the file name
|
||||
//!
|
||||
//! char* is marshaled as an LPStr, which on Linux is UTF-8.
|
||||
//! @endparblock
|
||||
//!
|
||||
//! @exception errno Passes these errors via errno to GetLastError:
|
||||
//! - ERROR_INVALID_PARAMETER: parameter is not valid
|
||||
//! - ERROR_FILE_NOT_FOUND: file does not exist
|
||||
//! - ERROR_ACCESS_DENIED: access is denied
|
||||
//! - ERROR_INVALID_ADDRESS: attempt to access invalid address
|
||||
//! - ERROR_STOPPED_ON_SYMLINK: too many symbolic links
|
||||
//! - ERROR_GEN_FAILURE: I/O error occurred
|
||||
//! - ERROR_INVALID_NAME: file provided is not a symbolic link
|
||||
//! - ERROR_INVALID_FUNCTION: incorrect function
|
||||
//! - ERROR_BAD_PATH_NAME: pathname is too long
|
||||
//! - ERROR_OUTOFMEMORY insufficient kernal memory
|
||||
//!
|
||||
//! @retval target path, or NULL if unsuccessful
|
||||
//!
|
||||
|
||||
char* FollowSymLink(const char* fileName)
|
||||
{
|
||||
errno = 0;
|
||||
|
||||
// Check parameters
|
||||
if (!fileName)
|
||||
{
|
||||
errno = ERROR_INVALID_PARAMETER;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char buffer[PATH_MAX];
|
||||
ssize_t sz = readlink(fileName, buffer, PATH_MAX);
|
||||
|
||||
if (sz == -1)
|
||||
{
|
||||
switch(errno)
|
||||
{
|
||||
case EACCES:
|
||||
errno = ERROR_ACCESS_DENIED;
|
||||
break;
|
||||
case EFAULT:
|
||||
errno = ERROR_INVALID_ADDRESS;
|
||||
break;
|
||||
case EINVAL:
|
||||
errno = ERROR_INVALID_NAME;
|
||||
break;
|
||||
case EIO:
|
||||
errno = ERROR_GEN_FAILURE;
|
||||
break;
|
||||
case ELOOP:
|
||||
errno = ERROR_STOPPED_ON_SYMLINK;
|
||||
break;
|
||||
case ENAMETOOLONG:
|
||||
errno = ERROR_BAD_PATH_NAME;
|
||||
break;
|
||||
case ENOENT:
|
||||
errno = ERROR_FILE_NOT_FOUND;
|
||||
break;
|
||||
case ENOMEM:
|
||||
errno = ERROR_OUTOFMEMORY;
|
||||
break;
|
||||
case ENOTDIR:
|
||||
errno = ERROR_BAD_PATH_NAME;
|
||||
break;
|
||||
default:
|
||||
errno = ERROR_INVALID_FUNCTION;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buffer[sz] = '\0';
|
||||
return strndup(buffer, sz + 1);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
char* FollowSymLink(const char* fileName);
|
||||
|
||||
PAL_END_EXTERNC
|
||||
@@ -0,0 +1,45 @@
|
||||
//! @file getcomputername.cpp
|
||||
//! @author George Fleming <v-geflem@microsoft>
|
||||
//! @brief Implements GetComputerName Win32 API
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
#include "getcomputername.h"
|
||||
|
||||
//! @brief GetComputerName retrieves the name of the host associated with
|
||||
//! the current thread.
|
||||
//!
|
||||
//! @exception errno Passes these errors via errno to GetLastError:
|
||||
//! - ERROR_INVALID_FUNCTION: getlogin_r() returned an unrecognized error code
|
||||
//! - ERROR_INVALID_ADDRESS: buffer is an invalid address
|
||||
//! - ERROR_GEN_FAILURE: buffer not large enough
|
||||
//!
|
||||
//! @retval username as UTF-8 string, or null if unsuccessful
|
||||
|
||||
char* GetComputerName()
|
||||
{
|
||||
errno = 0;
|
||||
// Get computername from system, note that gethostname(2) gets the
|
||||
// nodename from uname
|
||||
std::string computername(_POSIX_HOST_NAME_MAX, 0);
|
||||
int err = gethostname(&computername[0], computername.length());
|
||||
// Map errno to Win32 Error Codes
|
||||
if (err != 0)
|
||||
{
|
||||
switch (errno)
|
||||
{
|
||||
case EFAULT:
|
||||
errno = ERROR_INVALID_ADDRESS;
|
||||
break;
|
||||
case ENAMETOOLONG:
|
||||
errno = ERROR_GEN_FAILURE;
|
||||
break;
|
||||
default:
|
||||
errno = ERROR_INVALID_FUNCTION;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return strdup(computername.c_str());
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
char *GetComputerName();
|
||||
|
||||
PAL_END_EXTERNC
|
||||
@@ -0,0 +1,9 @@
|
||||
#include "getcurrentprocessorid.h"
|
||||
#include <unistd.h>
|
||||
|
||||
int32_t GetCurrentProcessId()
|
||||
{
|
||||
pid_t pid = getpid();
|
||||
return static_cast<int32_t>(pid);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
int32_t GetCurrentProcessId();
|
||||
|
||||
PAL_END_EXTERNC
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#include "getcurrentthreadid.h"
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
|
||||
HANDLE GetCurrentThreadId()
|
||||
{
|
||||
pid_t tid = pthread_self();
|
||||
return reinterpret_cast<HANDLE>(tid);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
HANDLE GetCurrentThreadId();
|
||||
|
||||
PAL_END_EXTERNC
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
//! @file getfullyqualifiedname.cpp
|
||||
//! @author George Fleming <v-geflem@microsoft.com>
|
||||
//! @brief Implements GetFullyQualifiedName on Linux
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include "getcomputername.h"
|
||||
#include "getfullyqualifiedname.h"
|
||||
|
||||
//! @brief GetFullyQualifiedName retrieves the fully qualifed dns name of the host
|
||||
//!
|
||||
//! @exception errno Passes these errors via errno to GetLastError:
|
||||
//! - ERROR_INVALID_FUNCTION: getlogin_r() returned an unrecognized error code (from GetComputerName)
|
||||
//! - ERROR_INVALID_ADDRESS: buffer is an invalid address (from GetComputerName)
|
||||
//! - ERROR_GEN_FAILURE: buffer not large enough (from GetComputerName)
|
||||
//! - ERROR_BAD_NET_NAME: Cannot determine network short name
|
||||
//!
|
||||
//! @retval username as UTF-8 string, or null if unsuccessful
|
||||
//!
|
||||
|
||||
char *GetFullyQualifiedName()
|
||||
{
|
||||
errno = 0;
|
||||
|
||||
char *computerName = GetComputerName();
|
||||
if (computerName == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (strchr(computerName, '.') != NULL)
|
||||
{
|
||||
return computerName;
|
||||
}
|
||||
|
||||
struct addrinfo hints, *info;
|
||||
|
||||
memset(&hints, 0, sizeof hints);
|
||||
hints.ai_family = AF_UNSPEC; /*either IPV4 or IPV6*/
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
|
||||
/* There are several ways to get the domain name:
|
||||
* uname(2), gethostbyname(3), resolver(3), getdomainname(2),
|
||||
* and getaddrinfo(3). Some of these are not portable, some aren't
|
||||
* POSIX compliant, and some are being deprecated. getaddrinfo seems
|
||||
* to be the best choice.
|
||||
*/
|
||||
if (getaddrinfo(computerName, "http", &hints, &info) != 0)
|
||||
{
|
||||
errno = ERROR_BAD_NET_NAME;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// info is actually a link-list. We'll just return the first full name
|
||||
|
||||
char *fullName = strndup(info->ai_canonname, strlen(info->ai_canonname));
|
||||
|
||||
freeaddrinfo(info);
|
||||
free(computerName);
|
||||
return fullName;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
char *GetFullyQualifiedName();
|
||||
|
||||
PAL_END_EXTERNC
|
||||
@@ -0,0 +1,104 @@
|
||||
//! @file getlinkcount.cpp
|
||||
//! @author George FLeming <v-geflem@microsoft.com>
|
||||
//! @brief Retrieve link count of a file
|
||||
|
||||
#include <errno.h>
|
||||
#include <locale.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
#include "getlinkcount.h"
|
||||
|
||||
//! @brief GetLinkCount retrieves the file link count (number of hard links)
|
||||
//! for the given file
|
||||
//!
|
||||
//! GetLinkCount
|
||||
//!
|
||||
//! @param[in] fileName
|
||||
//! @parblock
|
||||
//! A pointer to the buffer that contains the file name
|
||||
//!
|
||||
//! char* is marshaled as an LPStr, which on Linux is UTF-8.
|
||||
//! @endparblock
|
||||
//!
|
||||
//! @param[out] count
|
||||
//! @parblock
|
||||
//! This function returns the number of hard links associated with this file
|
||||
//! @endparblock
|
||||
//!
|
||||
//! @exception errno Passes these errors via errno to GetLastError:
|
||||
//! - ERROR_INVALID_PARAMETER: parameter is not valid
|
||||
//! - ERROR_FILE_NOT_FOUND: file does not exist
|
||||
//! - ERROR_ACCESS_DENIED: access is denied
|
||||
//! - ERROR_FILE_NOT_FOUND: the system cannot find the file specified
|
||||
//! - ERROR_INVALID_ADDRESS: attempt to access invalid address
|
||||
//! - ERROR_STOPPED_ON_SYMLINK: the operation stopped after reaching a symbolic link
|
||||
//! - ERROR_GEN_FAILURE: device attached to the system is not functioning
|
||||
//! - ERROR_NO_SUCH_USER: there was no corresponding entry in the utmp-file
|
||||
//! - ERROR_INVALID_NAME: filename, directory name, or volume label syntax is incorrect
|
||||
//! - ERROR_BUFFER_OVERFLOW: file name is too long
|
||||
//! - ERROR_INVALID_FUNCTION: incorrect function
|
||||
//! - ERROR_BAD_PATH_NAME: pathname is too long, or contains invalid characters
|
||||
//!
|
||||
//! @retval 1 If the function succeeds, and the variable pointed to by buffer contains
|
||||
//! infomation about the files
|
||||
//! @retval 0 If the function fails, the return value is zero. To get
|
||||
//! extended error information, call GetLastError.
|
||||
//!
|
||||
|
||||
int32_t GetLinkCount(const char* fileName, int32_t *count)
|
||||
{
|
||||
errno = 0;
|
||||
|
||||
// Check parameters
|
||||
if (!fileName)
|
||||
{
|
||||
errno = ERROR_INVALID_PARAMETER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct stat statBuf;
|
||||
|
||||
int returnCode = lstat(fileName, &statBuf);
|
||||
|
||||
if (returnCode != 0)
|
||||
{
|
||||
switch(errno)
|
||||
{
|
||||
case EACCES:
|
||||
errno = ERROR_ACCESS_DENIED;
|
||||
break;
|
||||
case EBADF:
|
||||
errno = ERROR_FILE_NOT_FOUND;
|
||||
break;
|
||||
case EFAULT:
|
||||
errno = ERROR_INVALID_ADDRESS;
|
||||
break;
|
||||
case ELOOP:
|
||||
errno = ERROR_STOPPED_ON_SYMLINK;
|
||||
break;
|
||||
case ENAMETOOLONG:
|
||||
errno = ERROR_GEN_FAILURE;
|
||||
break;
|
||||
case ENOENT:
|
||||
errno = ERROR_FILE_NOT_FOUND;
|
||||
break;
|
||||
case ENOMEM:
|
||||
errno = ERROR_NO_SUCH_USER;
|
||||
break;
|
||||
case ENOTDIR:
|
||||
errno = ERROR_INVALID_NAME;
|
||||
break;
|
||||
case EOVERFLOW:
|
||||
errno = ERROR_BUFFER_OVERFLOW;
|
||||
break;
|
||||
default:
|
||||
errno = ERROR_INVALID_FUNCTION;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
*count = statBuf.st_nlink;
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
int32_t GetLinkCount(const char* fileName, int32_t *count);
|
||||
|
||||
PAL_END_EXTERNC
|
||||
@@ -0,0 +1,65 @@
|
||||
//! @file getusername.cpp
|
||||
//! @author Andrew Schwartzmeyer <andschwa@microsoft.com>
|
||||
//! @brief Implements GetUserName for Linux
|
||||
|
||||
#include <errno.h>
|
||||
#include <locale.h>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
#include <pwd.h>
|
||||
#include "getusername.h"
|
||||
|
||||
//! @brief GetUserName retrieves the name of the user associated with
|
||||
//! the current thread.
|
||||
//!
|
||||
//! @exception errno Passes these errors via errno to GetLastError:
|
||||
//! - ERROR_INVALID_PARAMETER: parameter is not valid
|
||||
//! - ERROR_NO_SUCH_USER: there was no corresponding user
|
||||
//! - ERROR_GEN_FAILURE: sysconf() or getpwuid() failed for unknown reasons
|
||||
//!
|
||||
//! @retval username as UTF-8 string, or null if unsuccessful
|
||||
char* GetUserName()
|
||||
{
|
||||
errno = 0;
|
||||
|
||||
struct passwd pwd;
|
||||
struct passwd* result;
|
||||
// gets the initial suggested size for buf
|
||||
int buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
|
||||
if (buflen == -1)
|
||||
{
|
||||
errno = ERROR_GEN_FAILURE;
|
||||
return NULL;
|
||||
}
|
||||
std::string buf(buflen, 0);
|
||||
|
||||
// geteuid() gets the effective user ID of the calling process, and is always successful
|
||||
int ret = getpwuid_r(geteuid(), &pwd, &buf[0], buflen, &result);
|
||||
|
||||
// Map errno to Win32 Error Codes
|
||||
if (ret)
|
||||
{
|
||||
switch (errno)
|
||||
{
|
||||
case ENOENT:
|
||||
case ESRCH:
|
||||
case EBADF:
|
||||
case EPERM:
|
||||
errno = ERROR_NO_SUCH_USER;
|
||||
break;
|
||||
default:
|
||||
errno = ERROR_GEN_FAILURE;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Check if no user matched
|
||||
if (result == NULL)
|
||||
{
|
||||
errno = ERROR_NO_SUCH_USER;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// allocate copy on heap so CLR can free it
|
||||
return strdup(result->pw_name);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
char* GetUserName();
|
||||
|
||||
PAL_END_EXTERNC
|
||||
@@ -0,0 +1,81 @@
|
||||
//! @file isExecutable.cpp
|
||||
//! @author George FLeming <v-geflem@microsoft.com>
|
||||
//! @brief returns whether a file is executable
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
#include "isexecutable.h"
|
||||
|
||||
//! @brief IsExecutable determines if path is executable
|
||||
//!
|
||||
//! IsExecutable
|
||||
//!
|
||||
//! @param[in] fileName
|
||||
//! @parblock
|
||||
//! A pointer to the buffer that contains the file name
|
||||
//!
|
||||
//! char* is marshaled as an LPStr, which on Linux is UTF-8.
|
||||
//! @endparblock
|
||||
//!
|
||||
//! @exception errno Passes these errors via errno to GetLastError:
|
||||
//! - ERROR_FILE_NOT_FOUND: the system cannot find the file specified
|
||||
//! - ERROR_INVALID_ADDRESS: attempt to access invalid address
|
||||
//! - ERROR_GEN_FAILURE: device attached to the system is not functioning
|
||||
//! - ERROR_INVALID_NAME: filename, directory name, or volume label syntax is incorrect
|
||||
//! - ERROR_INVALID_FUNCTION: incorrect function
|
||||
//! - ERROR_INVALID_PARAMETER: parameter to access(2) call is incorrect
|
||||
//!
|
||||
//! @retval 1 if path is an executable
|
||||
//! @retval 0 if path is not a executable
|
||||
//! @retval -1 If the function fails.. To get extended error information, call GetLastError.
|
||||
//!
|
||||
|
||||
int32_t IsExecutable(const char* fileName)
|
||||
{
|
||||
errno = 0;
|
||||
|
||||
// Check parameters
|
||||
if (!fileName)
|
||||
{
|
||||
errno = ERROR_INVALID_PARAMETER;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int returnCode = access(fileName, X_OK);
|
||||
|
||||
if (returnCode == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch(errno)
|
||||
{
|
||||
case EACCES:
|
||||
return 0;
|
||||
case EBADF:
|
||||
case ENOENT:
|
||||
errno = ERROR_FILE_NOT_FOUND;
|
||||
break;
|
||||
case EFAULT:
|
||||
errno = ERROR_INVALID_ADDRESS;
|
||||
break;
|
||||
case ELOOP:
|
||||
errno = ERROR_STOPPED_ON_SYMLINK;
|
||||
break;
|
||||
case EIO:
|
||||
case ENOMEM:
|
||||
errno = ERROR_GEN_FAILURE;
|
||||
break;
|
||||
case ENOTDIR:
|
||||
case ENAMETOOLONG:
|
||||
errno = ERROR_INVALID_NAME;
|
||||
break;
|
||||
case EINVAL:
|
||||
errno = ERROR_INVALID_PARAMETER;
|
||||
break;
|
||||
default:
|
||||
errno = ERROR_INVALID_FUNCTION;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
int32_t IsExecutable(const char* fileName);
|
||||
|
||||
PAL_END_EXTERNC
|
||||
@@ -0,0 +1,96 @@
|
||||
//! @file isSymLink.cpp
|
||||
//! @author George FLeming <v-geflem@microsoft.com>
|
||||
//! @brief returns whether a path is a symbolic link
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
#include "issymlink.h"
|
||||
|
||||
//! @brief IsSymLink determines if path is a symbolic link
|
||||
//!
|
||||
//! IsSymLink
|
||||
//!
|
||||
//! @param[in] fileName
|
||||
//! @parblock
|
||||
//! A pointer to the buffer that contains the file name
|
||||
//!
|
||||
//! char* is marshaled as an LPStr, which on Linux is UTF-8.
|
||||
//! @endparblock
|
||||
//!
|
||||
//! @exception errno Passes these errors via errno to GetLastError:
|
||||
//! - ERROR_INVALID_PARAMETER: parameter is not valid
|
||||
//! - ERROR_FILE_NOT_FOUND: file does not exist
|
||||
//! - ERROR_ACCESS_DENIED: access is denied
|
||||
//! - ERROR_FILE_NOT_FOUND: the system cannot find the file specified
|
||||
//! - ERROR_INVALID_ADDRESS: attempt to access invalid address
|
||||
//! - ERROR_STOPPED_ON_SYMLINK: the operation stopped after reaching a symbolic link
|
||||
//! - ERROR_GEN_FAILURE: device attached to the system is not functioning
|
||||
//! - ERROR_NO_SUCH_USER: there was no corresponding entry in the utmp-file
|
||||
//! - ERROR_INVALID_NAME: filename, directory name, or volume label syntax is incorrect
|
||||
//! - ERROR_BUFFER_OVERFLOW: file name is too long
|
||||
//! - ERROR_INVALID_FUNCTION: incorrect function
|
||||
//! - ERROR_BAD_PATH_NAME: pathname is too long, or contains invalid characters
|
||||
//!
|
||||
//! @retval 1 if path is a symbolic link
|
||||
//! @retval 0 if path is not a symbolic link
|
||||
//! @retval -1 If the function fails.. To get extended error information, call GetLastError.
|
||||
//!
|
||||
|
||||
int32_t IsSymLink(const char* fileName)
|
||||
{
|
||||
|
||||
errno = 0;
|
||||
|
||||
// Check parameters
|
||||
if (!fileName)
|
||||
{
|
||||
errno = ERROR_INVALID_PARAMETER;
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct stat statBuf;
|
||||
|
||||
int returnCode = lstat(fileName, &statBuf);
|
||||
|
||||
if (returnCode != 0)
|
||||
{
|
||||
switch(errno)
|
||||
{
|
||||
case EACCES:
|
||||
errno = ERROR_ACCESS_DENIED;
|
||||
break;
|
||||
case EBADF:
|
||||
errno = ERROR_FILE_NOT_FOUND;
|
||||
break;
|
||||
case EFAULT:
|
||||
errno = ERROR_INVALID_ADDRESS;
|
||||
break;
|
||||
case ELOOP:
|
||||
errno = ERROR_STOPPED_ON_SYMLINK;
|
||||
break;
|
||||
case ENAMETOOLONG:
|
||||
errno = ERROR_GEN_FAILURE;
|
||||
break;
|
||||
case ENOENT:
|
||||
errno = ERROR_FILE_NOT_FOUND;
|
||||
break;
|
||||
case ENOMEM:
|
||||
errno = ERROR_NO_SUCH_USER;
|
||||
break;
|
||||
case ENOTDIR:
|
||||
errno = ERROR_INVALID_NAME;
|
||||
break;
|
||||
case EOVERFLOW:
|
||||
errno = ERROR_BUFFER_OVERFLOW;
|
||||
break;
|
||||
default:
|
||||
errno = ERROR_INVALID_FUNCTION;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
return S_ISLNK(statBuf.st_mode) ? 1 : 0;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
int32_t IsSymLink(const char* fileName);
|
||||
|
||||
PAL_END_EXTERNC
|
||||
@@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
|
||||
#define ERROR_INVALID_PARAMETER 87
|
||||
#define ERROR_OUTOFMEMORY 14
|
||||
#define ERROR_BAD_ENVIRONMENT 0x0000000A
|
||||
#define ERROR_TOO_MANY_OPEN_FILES 0x00000004
|
||||
#define ERROR_INSUFFICIENT_BUFFER 0x0000007A
|
||||
#define ERROR_NO_ASSOCIATION 0x00000483
|
||||
#define ERROR_NO_SUCH_USER 0x00000525
|
||||
#define ERROR_INVALID_FUNCTION 0x00000001
|
||||
#define ERROR_INVALID_ADDRESS 0x000001e7
|
||||
#define ERROR_GEN_FAILURE 0x0000001F
|
||||
#define ERROR_ACCESS_DENIED 0x00000005
|
||||
#define ERROR_INVALID_NAME 0x0000007B
|
||||
#define ERROR_STOPPED_ON_SYMLINK 0x000002A9
|
||||
#define ERROR_BUFFER_OVERFLOW 0x0000006F
|
||||
#define ERROR_FILE_NOT_FOUND 0x00000002
|
||||
#define ERROR_BAD_PATH_NAME 0x000000A1
|
||||
#define ERROR_BAD_NET_NAME 0x00000043
|
||||
#define ERROR_DISK_FULL 0x00000070
|
||||
#define ERROR_FILE_EXISTS 0x00000050
|
||||
#define ERROR_TOO_MANY_LINKS 0x00000476
|
||||
|
||||
/*
|
||||
**==============================================================================
|
||||
**
|
||||
** PAL_BEGIN_EXTERNC
|
||||
** PAL_END_EXTERNC
|
||||
**
|
||||
**==============================================================================
|
||||
*/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
# define PAL_BEGIN_EXTERNC extern "C" {
|
||||
# define PAL_END_EXTERNC }
|
||||
#else
|
||||
# define PAL_BEGIN_EXTERNC
|
||||
# define PAL_END_EXTERNC
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
//! @file setdate.cpp
|
||||
//! @author George FLeming <v-geflem@microsoft.com>
|
||||
//! @brief set local/system date and time
|
||||
|
||||
#include <errno.h>
|
||||
#include <langinfo.h>
|
||||
#include <locale.h>
|
||||
#include <string>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include "setdate.h"
|
||||
|
||||
//! @brief SetDate sets the date and time on local computer. You must
|
||||
//! be super-user to set the time.
|
||||
//!
|
||||
//! SetDate
|
||||
//!
|
||||
//! @param[in] info
|
||||
//! @parblock
|
||||
//! A struct that contains program to execute and its parameters
|
||||
//!
|
||||
//! @exception errno Passes these errors via errno to GetLastError:
|
||||
//! - ERROR_BAD_ENVIRONMENT: locale is not UTF-8
|
||||
//! - ERROR_INVALID_PARAMETER: time was not passed in correctly
|
||||
//! - ERROR_ACCESS_DENIED: you must be super-user to set the date
|
||||
//!
|
||||
//! @retval 0 successfully set date
|
||||
//! @retval -1 if failure occurred. To get extended error information, call GetLastError.
|
||||
//!
|
||||
|
||||
int32_t SetDate(const SetDateInfo &info)
|
||||
{
|
||||
errno = 0;
|
||||
|
||||
// Select locale from environment
|
||||
setlocale(LC_ALL, "");
|
||||
// Check that locale is UTF-8
|
||||
if (nl_langinfo(CODESET) != std::string("UTF-8"))
|
||||
{
|
||||
errno = ERROR_BAD_ENVIRONMENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct tm bdTime;
|
||||
struct timeval tv;
|
||||
|
||||
bdTime.tm_year = info.Year - 1900;
|
||||
bdTime.tm_mon = info.Month - 1; // This is zero-based
|
||||
bdTime.tm_mday = info.Day;
|
||||
bdTime.tm_hour = info.Hour;
|
||||
bdTime.tm_min = info.Minute;
|
||||
bdTime.tm_sec = info.Second;
|
||||
bdTime.tm_isdst = info.DST;
|
||||
|
||||
time_t newTime = mktime(&bdTime);
|
||||
if (newTime == -1)
|
||||
{
|
||||
errno = ERROR_INVALID_PARAMETER;
|
||||
return -1;
|
||||
}
|
||||
|
||||
tv.tv_sec = newTime;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
int result = settimeofday(&tv, NULL);
|
||||
if (result == -1)
|
||||
{
|
||||
errno = ERROR_ACCESS_DENIED;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
typedef struct setDateInfo
|
||||
{
|
||||
// the order of members does matter here
|
||||
int32_t Year;
|
||||
int32_t Month;
|
||||
int32_t Day;
|
||||
int32_t Hour;
|
||||
int32_t Minute;
|
||||
int32_t Second;
|
||||
int32_t Millisecond;
|
||||
int32_t DST;
|
||||
} SetDateInfo;
|
||||
|
||||
int32_t SetDate(const SetDateInfo &info);
|
||||
|
||||
PAL_END_EXTERNC
|
||||
@@ -0,0 +1,22 @@
|
||||
add_subdirectory(googletest)
|
||||
|
||||
add_executable(psl-native-test
|
||||
test-locale.cpp
|
||||
test-getcurrentprocessid.cpp
|
||||
test-getusername.cpp
|
||||
test-getcomputername.cpp
|
||||
test-getlinkcount.cpp
|
||||
test-getfullyqualifiedname.cpp
|
||||
test-issymlink.cpp
|
||||
test-isexecutable.cpp
|
||||
test-createsymlink.cpp
|
||||
test-createhardlink.cpp
|
||||
main.cpp)
|
||||
|
||||
# manually include gtest headers
|
||||
target_include_directories(psl-native-test PRIVATE ${gtest_SOURCE_DIR}/include)
|
||||
|
||||
target_link_libraries(psl-native-test psl-native gtest)
|
||||
|
||||
add_test(NAME psl-native-test
|
||||
COMMAND psl-native-test --gtest_output=xml:native-tests.xml)
|
||||
Submodule
+1
Submodule src/libpsl-native/test/googletest added at c99458533a.
@@ -0,0 +1,7 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
//! @file test-createhardlink.cpp
|
||||
//! @author George Fleming <v-geflem@microsoft.com>
|
||||
//! @brief Implements test for CreateHardLink()
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include "getlinkcount.h"
|
||||
#include "createhardlink.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class CreateHardLinkTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
|
||||
static const int bufSize = 64;
|
||||
const string fileTemplate = "/tmp/symlinktest.fXXXXXX";
|
||||
const string dirTemplate = "/tmp/symlinktest.dXXXXXX";
|
||||
const string fileHardLink = "/tmp/symlinktest.flink";
|
||||
const string dirHardLink = "/tmp/symlinktest.dlink";
|
||||
char *file, *dir;
|
||||
char fileTemplateBuf[bufSize], dirTemplateBuf[bufSize];
|
||||
|
||||
CreateHardLinkTest()
|
||||
{
|
||||
// since mkstemp and mkdtemp modifies the template string, let's give them writable buffers
|
||||
strcpy(fileTemplateBuf, fileTemplate.c_str());
|
||||
strcpy(dirTemplateBuf, dirTemplate.c_str());
|
||||
|
||||
// First create a temp file
|
||||
int fd = mkstemp(fileTemplateBuf);
|
||||
EXPECT_TRUE(fd != -1);
|
||||
file = fileTemplateBuf;
|
||||
|
||||
// Create a temp directory
|
||||
dir = mkdtemp(dirTemplateBuf);
|
||||
EXPECT_TRUE(dir != NULL);
|
||||
|
||||
// Create hard link to file
|
||||
int ret1 = CreateHardLink(fileHardLink.c_str(), file);
|
||||
EXPECT_EQ(ret1, 1);
|
||||
|
||||
// Create hard link to directory - should fail
|
||||
int ret2 = CreateHardLink(dirHardLink.c_str(), dir);
|
||||
EXPECT_EQ(ret2, 0);
|
||||
}
|
||||
|
||||
~CreateHardLinkTest()
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = unlink(fileHardLink.c_str());
|
||||
EXPECT_EQ(0, ret);
|
||||
|
||||
ret = unlink(file);
|
||||
EXPECT_EQ(0, ret);
|
||||
|
||||
ret = rmdir(dir);
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(CreateHardLinkTest, FilePathNameIsNull)
|
||||
{
|
||||
int retVal = CreateHardLink(NULL, NULL);
|
||||
EXPECT_EQ(retVal, 0);
|
||||
EXPECT_EQ(ERROR_INVALID_PARAMETER, errno);
|
||||
}
|
||||
|
||||
TEST_F(CreateHardLinkTest, FilePathNameDoesNotExist)
|
||||
{
|
||||
std::string invalidFile = "/tmp/symlinktest_invalidFile";
|
||||
std::string invalidLink = "/tmp/symlinktest_invalidLink";
|
||||
|
||||
// make sure neither exists
|
||||
unlink(invalidFile.c_str());
|
||||
unlink(invalidLink.c_str());
|
||||
|
||||
int retVal = CreateHardLink(invalidLink.c_str(), invalidFile.c_str());
|
||||
EXPECT_EQ(retVal, 0);
|
||||
}
|
||||
|
||||
TEST_F(CreateHardLinkTest, VerifyLinkCount)
|
||||
{
|
||||
int count = 0;
|
||||
int retVal = GetLinkCount(fileHardLink.c_str(), &count);
|
||||
EXPECT_EQ(1, retVal);
|
||||
EXPECT_EQ(2, count);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
//! @file test-createsymlink.cpp
|
||||
//! @author George Fleming <v-geflem@microsoft.com>
|
||||
//! @brief Implements test for CreateSymLink() and FollowSymLink()
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include "issymlink.h"
|
||||
#include "createsymlink.h"
|
||||
#include "followsymlink.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class CreateSymLinkTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
|
||||
static const int bufSize = 64;
|
||||
const string fileTemplate = "/tmp/symlinktest.fXXXXXX";
|
||||
const string dirTemplate = "/tmp/symlinktest.dXXXXXX";
|
||||
const string fileSymLink = "/tmp/symlinktest.flink";
|
||||
const string dirSymLink = "/tmp/symlinktest.dlink";
|
||||
char *file, *dir;
|
||||
char fileTemplateBuf[bufSize], dirTemplateBuf[bufSize];
|
||||
|
||||
CreateSymLinkTest()
|
||||
{
|
||||
// since mkstemp and mkdtemp modifies the template string, let's give them writable buffers
|
||||
strcpy(fileTemplateBuf, fileTemplate.c_str());
|
||||
strcpy(dirTemplateBuf, dirTemplate.c_str());
|
||||
|
||||
// First create a temp file
|
||||
int fd = mkstemp(fileTemplateBuf);
|
||||
EXPECT_TRUE(fd != -1);
|
||||
file = fileTemplateBuf;
|
||||
|
||||
// Create a temp directory
|
||||
dir = mkdtemp(dirTemplateBuf);
|
||||
EXPECT_TRUE(dir != NULL);
|
||||
|
||||
// Create symbolic link to file
|
||||
int ret1 = CreateSymLink(fileSymLink.c_str(), file);
|
||||
EXPECT_EQ(ret1, 1);
|
||||
|
||||
// Create symbolic link to directory
|
||||
int ret2 = CreateSymLink(dirSymLink.c_str(), dir);
|
||||
EXPECT_EQ(ret2, 1);
|
||||
}
|
||||
|
||||
~CreateSymLinkTest()
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = unlink(fileSymLink.c_str());
|
||||
EXPECT_EQ(0, ret);
|
||||
|
||||
ret = unlink(dirSymLink.c_str());
|
||||
EXPECT_EQ(0, ret);
|
||||
|
||||
ret = unlink(file);
|
||||
EXPECT_EQ(0, ret);
|
||||
|
||||
ret = rmdir(dir);
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(CreateSymLinkTest, FilePathNameIsNull)
|
||||
{
|
||||
int retVal = CreateSymLink(NULL, NULL);
|
||||
EXPECT_EQ(retVal, 0);
|
||||
EXPECT_EQ(ERROR_INVALID_PARAMETER, errno);
|
||||
}
|
||||
|
||||
TEST_F(CreateSymLinkTest, FilePathNameDoesNotExist)
|
||||
{
|
||||
std::string invalidFile = "/tmp/symlinktest_invalidFile";
|
||||
std::string invalidLink = "/tmp/symlinktest_invalidLink";
|
||||
|
||||
// make sure neither exists
|
||||
unlink(invalidFile.c_str());
|
||||
unlink(invalidLink.c_str());
|
||||
|
||||
// Linux allows creation of symbolic link that points to an invalid file
|
||||
int retVal = CreateSymLink(invalidLink.c_str(), invalidFile.c_str());
|
||||
EXPECT_EQ(retVal, 1);
|
||||
|
||||
std::string target = FollowSymLink(invalidLink.c_str());
|
||||
EXPECT_EQ(target, invalidFile);
|
||||
|
||||
unlink(invalidLink.c_str());
|
||||
}
|
||||
|
||||
TEST_F(CreateSymLinkTest, SymLinkToFile)
|
||||
{
|
||||
int retVal = IsSymLink(fileSymLink.c_str());
|
||||
EXPECT_EQ(1, retVal);
|
||||
|
||||
std::string target = FollowSymLink(fileSymLink.c_str());
|
||||
EXPECT_EQ(target, file);
|
||||
}
|
||||
|
||||
TEST_F(CreateSymLinkTest, SymLinkToDirectory)
|
||||
{
|
||||
int retVal = IsSymLink(dirSymLink.c_str());
|
||||
EXPECT_EQ(1, retVal);
|
||||
|
||||
std::string target = FollowSymLink(dirSymLink.c_str());
|
||||
EXPECT_EQ(target, dir);
|
||||
}
|
||||
|
||||
TEST_F(CreateSymLinkTest, SymLinkAgain)
|
||||
{
|
||||
int retVal = CreateSymLink(fileSymLink.c_str(), file);
|
||||
EXPECT_EQ(0, retVal);
|
||||
EXPECT_EQ(ERROR_FILE_EXISTS, errno);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
//! @file test-getcomputername.cpp
|
||||
//! @author George Fleming <v-geflem@microsoft.com>
|
||||
//! @brief Unit tests for GetComputerName
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include "getcomputername.h"
|
||||
|
||||
//! Test fixture for GetComputerNameTest
|
||||
class GetComputerNameTest : public ::testing::Test
|
||||
{
|
||||
};
|
||||
|
||||
TEST_F(GetComputerNameTest, Success)
|
||||
{
|
||||
char expectedComputerName[_POSIX_HOST_NAME_MAX];
|
||||
|
||||
// the gethostname system call gets the nodename from uname
|
||||
FILE *fPtr = popen("uname -n", "r");
|
||||
ASSERT_TRUE(fPtr != NULL);
|
||||
|
||||
char *linePtr = fgets(expectedComputerName, sizeof(expectedComputerName), fPtr);
|
||||
ASSERT_TRUE(linePtr != NULL);
|
||||
|
||||
// There's a tendency to have \n at end of fgets string, so remove it before compare
|
||||
size_t sz = strlen(expectedComputerName);
|
||||
if (sz > 0 && expectedComputerName[sz - 1] == '\n')
|
||||
{
|
||||
expectedComputerName[sz - 1] = '\0';
|
||||
}
|
||||
pclose(fPtr);
|
||||
|
||||
ASSERT_STREQ(GetComputerName(), expectedComputerName);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include "getcurrentprocessorid.h"
|
||||
|
||||
// This is a very simple test case to show how tests can be written
|
||||
TEST(GetCurrentProcessId,simple)
|
||||
{
|
||||
const int32_t currentProcessId = GetCurrentProcessId();
|
||||
const pid_t pid = getpid();
|
||||
|
||||
// first make sure that on this platform those types are of the same size
|
||||
ASSERT_TRUE(sizeof(int32_t) >= sizeof(pid_t));
|
||||
|
||||
// now compare the actual values
|
||||
ASSERT_EQ(currentProcessId,static_cast<int32_t>(pid));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include "getcurrentthreadid.h"
|
||||
#include <pthread.h>
|
||||
|
||||
TEST(GetCurrentThreadId,simple)
|
||||
{
|
||||
const HANDLE currentThreadId = GetCurrentThreadId();
|
||||
const pid_t tid = pthread_self();
|
||||
|
||||
// first make sure that on this platform those types are of the same size
|
||||
ASSERT_TRUE(sizeof(HANDLE) >= sizeof(pid_t));
|
||||
|
||||
// now compare the actual values
|
||||
ASSERT_EQ(currentThreadId,reinterpret_cast<HANDLE>(tid));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
//! @file test-getfullyqualifiedname.cpp
|
||||
//! @author George Fleming <v-geflem@microsoft.com>
|
||||
//! @brief Unit tests for GetFullyQualifiedName
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include "getfullyqualifiedname.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <string>
|
||||
|
||||
//! Test fixture for GetComputerNameTest
|
||||
class GetFullyQualifiedNameTest : public ::testing::Test
|
||||
{
|
||||
};
|
||||
|
||||
TEST_F(GetFullyQualifiedNameTest, ValidateLinuxGetFullyQualifiedDomainName)
|
||||
{
|
||||
std::string actual(GetFullyQualifiedName());
|
||||
|
||||
std::string hostname(_POSIX_HOST_NAME_MAX, 0);
|
||||
ASSERT_FALSE(gethostname(&hostname[0], hostname.length()));
|
||||
// trim null characters from string
|
||||
hostname = std::string(hostname.c_str());
|
||||
|
||||
struct addrinfo hints, *info;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
ASSERT_FALSE(getaddrinfo(hostname.c_str(), "http", &hints, &info));
|
||||
|
||||
// Compare hostname part of FQDN
|
||||
ASSERT_EQ(hostname, actual.substr(0, hostname.length()));
|
||||
|
||||
// Compare canonical name to FQDN
|
||||
ASSERT_EQ(info->ai_canonname, actual);
|
||||
|
||||
freeaddrinfo(info);
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
//! @file test-getlinkcount.cpp
|
||||
//! @author George Fleming <v-geflem@microsoft.com>
|
||||
//! @brief Implements test for getLinkCount()
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <pwd.h>
|
||||
#include <fstream>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include "getlinkcount.h"
|
||||
|
||||
class getLinkCountTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
|
||||
static const int bufSize = 64;
|
||||
const std::string fileTemplate = "/tmp/createFile.XXXXXX";
|
||||
char fileTemplateBuf[bufSize];
|
||||
|
||||
int32_t count;
|
||||
char *file;
|
||||
|
||||
getLinkCountTest()
|
||||
{
|
||||
// since mkstemp modifies the template string, let's give it writable buffer
|
||||
strcpy(fileTemplateBuf, fileTemplate.c_str());
|
||||
|
||||
int fd = mkstemp(fileTemplateBuf);
|
||||
EXPECT_TRUE(fd != -1);
|
||||
file = fileTemplateBuf;
|
||||
}
|
||||
|
||||
void createFileForTesting(const std::string &theFile)
|
||||
{
|
||||
std::ofstream ofs;
|
||||
ofs.open(theFile, std::ofstream::out);
|
||||
ofs << "hi there, ms ostc!";
|
||||
ofs.close();
|
||||
}
|
||||
|
||||
std::string createHardLink(const std::string &origFile)
|
||||
{
|
||||
std::string newFile = origFile + "_link";
|
||||
int ret = link(origFile.c_str(), newFile.c_str());
|
||||
EXPECT_EQ(0, ret);
|
||||
|
||||
return newFile;
|
||||
}
|
||||
|
||||
void removeFile(const std::string &fileName)
|
||||
{
|
||||
int ret = unlink(fileName.c_str());
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(getLinkCountTest, FilePathNameIsNull)
|
||||
{
|
||||
int32_t retVal = GetLinkCount(NULL, &count );
|
||||
ASSERT_FALSE(retVal);
|
||||
EXPECT_EQ(ERROR_INVALID_PARAMETER, errno);
|
||||
}
|
||||
|
||||
TEST_F(getLinkCountTest, FilePathNameDoesNotExist)
|
||||
{
|
||||
std::string invalidFile = "/tmp/createFile";
|
||||
int32_t retVal = GetLinkCount(invalidFile.c_str(), &count);
|
||||
ASSERT_FALSE(retVal);
|
||||
EXPECT_EQ(ERROR_FILE_NOT_FOUND, errno);
|
||||
}
|
||||
|
||||
TEST_F(getLinkCountTest, LinkCountOfSinglyLinkedFile)
|
||||
{
|
||||
createFileForTesting(file);
|
||||
int32_t retVal = GetLinkCount(file, &count);
|
||||
ASSERT_TRUE(retVal);
|
||||
EXPECT_EQ(1, count);
|
||||
|
||||
removeFile(file);
|
||||
}
|
||||
|
||||
TEST_F(getLinkCountTest, LinkCountOfMultipliLinkedFile)
|
||||
{
|
||||
createFileForTesting(file);
|
||||
std::string newFile = createHardLink(file);
|
||||
int32_t retVal = GetLinkCount(file, &count);
|
||||
ASSERT_TRUE(retVal);
|
||||
EXPECT_EQ(2, count);
|
||||
|
||||
removeFile(file);
|
||||
removeFile(newFile);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
//! @file test-getusername.cpp
|
||||
//! @author Andrew Schwartzmeyer <andschwa@microsoft.com>
|
||||
//! @brief Unit tests for GetUserName
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unistd.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <pwd.h>
|
||||
#include "getusername.h"
|
||||
|
||||
TEST(GetUserName, Success)
|
||||
{
|
||||
char* expected = getpwuid(geteuid())->pw_name;
|
||||
ASSERT_TRUE(expected != NULL);
|
||||
ASSERT_EQ(GetUserName(), std::string(expected));
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
//! @file test-isexecutable.cpp
|
||||
//! @author George Fleming <v-geflem@microsoft.com>
|
||||
//! @brief Implements test for isexecutable()
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include "isexecutable.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class IsExecutableTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
|
||||
static const int bufSize = 64;
|
||||
const string fileTemplate = "/tmp/isexecutabletest.fXXXXXXX";
|
||||
const mode_t mode_700 = S_IRUSR | S_IWUSR | S_IXUSR;
|
||||
const mode_t mode_070 = S_IRGRP | S_IWGRP | S_IXGRP;
|
||||
const mode_t mode_007 = S_IROTH | S_IWOTH | S_IXOTH;
|
||||
const mode_t mode_777 = mode_700 | mode_070 | mode_007;
|
||||
const mode_t mode_444 = S_IRUSR | S_IRGRP | S_IROTH;
|
||||
|
||||
char *file;
|
||||
char fileTemplateBuf[bufSize];
|
||||
|
||||
IsExecutableTest()
|
||||
{
|
||||
// since mkstemp modifies the template string, let's give it writable buffers
|
||||
strcpy(fileTemplateBuf, fileTemplate.c_str());
|
||||
|
||||
// First create a file
|
||||
int fd = mkstemp(fileTemplateBuf);
|
||||
EXPECT_TRUE(fd != -1);
|
||||
file = fileTemplateBuf;
|
||||
}
|
||||
|
||||
~IsExecutableTest()
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = unlink(file);
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
|
||||
void ChangeFilePermission(const char* file, mode_t mode)
|
||||
{
|
||||
int ret = chmod(file, mode);
|
||||
EXPECT_EQ(ret, 0);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(IsExecutableTest, FilePathNameIsNull)
|
||||
{
|
||||
int32_t retVal = IsExecutable(NULL);
|
||||
EXPECT_EQ(retVal, -1);
|
||||
EXPECT_EQ(ERROR_INVALID_PARAMETER, errno);
|
||||
}
|
||||
|
||||
TEST_F(IsExecutableTest, FilePathNameDoesNotExist)
|
||||
{
|
||||
std::string invalidFile = "/tmp/isexecutabletest_invalidFile";
|
||||
int32_t retVal = IsExecutable(invalidFile.c_str());
|
||||
EXPECT_EQ(retVal, -1);
|
||||
EXPECT_EQ(ERROR_FILE_NOT_FOUND, errno);
|
||||
}
|
||||
|
||||
TEST_F(IsExecutableTest, NormalFileIsNotIsexecutable)
|
||||
{
|
||||
int32_t retVal = IsExecutable(file);
|
||||
EXPECT_EQ(0, retVal);
|
||||
|
||||
ChangeFilePermission(file, mode_444);
|
||||
|
||||
retVal = IsExecutable(file);
|
||||
EXPECT_EQ(0, retVal);
|
||||
}
|
||||
|
||||
TEST_F(IsExecutableTest, FilePermission_700)
|
||||
{
|
||||
ChangeFilePermission(file, mode_700);
|
||||
|
||||
int32_t retVal = IsExecutable(file);
|
||||
EXPECT_EQ(1, retVal);
|
||||
}
|
||||
|
||||
TEST_F(IsExecutableTest, FilePermission_777)
|
||||
{
|
||||
ChangeFilePermission(file, mode_777);
|
||||
|
||||
int32_t retVal = IsExecutable(file);
|
||||
EXPECT_EQ(1, retVal);
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
//! @file test-issymlink.cpp
|
||||
//! @author George Fleming <v-geflem@microsoft.com>
|
||||
//! @brief Implements test for isSymLink()
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include "issymlink.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class isSymLinkTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
|
||||
static const int bufSize = 64;
|
||||
const string fileTemplate = "/tmp/symlinktest.fXXXXXX";
|
||||
const string dirTemplate = "/tmp/symlinktest.dXXXXXX";
|
||||
const string fileSymLink = "/tmp/symlinktest.flink";
|
||||
const string dirSymLink = "/tmp/symlinktest.dlink";
|
||||
char *file, *dir;
|
||||
char fileTemplateBuf[bufSize], dirTemplateBuf[bufSize];
|
||||
|
||||
isSymLinkTest()
|
||||
{
|
||||
// since mkstemp and mkdtemp modifies the template string, let's give them writable buffers
|
||||
strcpy(fileTemplateBuf, fileTemplate.c_str());
|
||||
strcpy(dirTemplateBuf, dirTemplate.c_str());
|
||||
|
||||
// First create a file
|
||||
int fd = mkstemp(fileTemplateBuf);
|
||||
EXPECT_TRUE(fd != -1);
|
||||
file = fileTemplateBuf;
|
||||
|
||||
// Create a temp directory
|
||||
dir = mkdtemp(dirTemplateBuf);
|
||||
EXPECT_TRUE(dir != NULL);
|
||||
|
||||
// Create symbolic link to file
|
||||
int ret1 = symlink(file, fileSymLink.c_str());
|
||||
EXPECT_EQ(ret1, 0);
|
||||
|
||||
// Create symbolic link to directory
|
||||
int ret2 = symlink(dir, dirSymLink.c_str());
|
||||
EXPECT_EQ(ret2, 0);
|
||||
}
|
||||
|
||||
~isSymLinkTest()
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = unlink(fileSymLink.c_str());
|
||||
EXPECT_EQ(0, ret);
|
||||
|
||||
ret = unlink(dirSymLink.c_str());
|
||||
EXPECT_EQ(0, ret);
|
||||
|
||||
ret = unlink(file);
|
||||
EXPECT_EQ(0, ret);
|
||||
|
||||
ret = rmdir(dir);
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(isSymLinkTest, FilePathNameIsNull)
|
||||
{
|
||||
int retVal = IsSymLink(NULL);
|
||||
EXPECT_EQ(retVal, -1);
|
||||
EXPECT_EQ(ERROR_INVALID_PARAMETER, errno);
|
||||
}
|
||||
|
||||
TEST_F(isSymLinkTest, FilePathNameDoesNotExist)
|
||||
{
|
||||
std::string invalidFile = "/tmp/symlinktest_invalidFile";
|
||||
int retVal = IsSymLink(invalidFile.c_str());
|
||||
EXPECT_EQ(retVal, -1);
|
||||
EXPECT_EQ(ERROR_FILE_NOT_FOUND, errno);
|
||||
}
|
||||
|
||||
TEST_F(isSymLinkTest, NormalFileIsNotSymLink)
|
||||
{
|
||||
int retVal = IsSymLink(file);
|
||||
EXPECT_EQ(0, retVal);
|
||||
}
|
||||
|
||||
TEST_F(isSymLinkTest, SymLinkToFile)
|
||||
{
|
||||
int retVal = IsSymLink(fileSymLink.c_str());
|
||||
EXPECT_EQ(1, retVal);
|
||||
}
|
||||
|
||||
TEST_F(isSymLinkTest, NormalDirectoryIsNotSymbLink)
|
||||
{
|
||||
int retVal = IsSymLink(dir);
|
||||
EXPECT_EQ(0, retVal);
|
||||
}
|
||||
|
||||
TEST_F(isSymLinkTest, SymLinkToDirectory)
|
||||
{
|
||||
int retVal = IsSymLink(dirSymLink.c_str());
|
||||
EXPECT_EQ(1, retVal);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
//! @file test-locale.cpp
|
||||
//! @author Alex Jordan <v-alexjo@microsoft.com>
|
||||
//! @brief Unit tests for linux locale
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <langinfo.h>
|
||||
#include <locale.h>
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
//! Test fixture for LocaleTest
|
||||
|
||||
class LocaleTest : public ::testing::Test
|
||||
{
|
||||
};
|
||||
|
||||
TEST_F(LocaleTest, Success)
|
||||
{
|
||||
setlocale (LC_ALL, "");
|
||||
ASSERT_FALSE (nl_langinfo(CODESET) == NULL);
|
||||
ASSERT_TRUE(nl_langinfo(CODESET) == std::string("UTF-8"));
|
||||
}
|
||||
@@ -3,6 +3,13 @@ project(PowerShell)
|
||||
|
||||
add_compile_options()
|
||||
|
||||
# set the output path for `powershell.exe`
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/../Microsoft.PowerShell.ConsoleHost")
|
||||
foreach(OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES})
|
||||
string(TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
||||
endforeach( OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES )
|
||||
|
||||
# set these flags, so build does static linking for msvcr120.dll
|
||||
# otherwise this dll need to be present on the system
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using System.Management.Automation;
|
||||
using Microsoft.PowerShell.Linux.Host;
|
||||
using Microsoft.PowerShell.Host;
|
||||
|
||||
// This collection fixture initializes Core PowerShell's AssemblyLoadContext once and only
|
||||
// once. Attempting to initialize in a class level fixture will cause multiple
|
||||
|
||||
Loaded 100 of 107 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user