mirror of
https://github.com/PowerShell/PowerShell.git
synced 2024-11-24 02:04:07 +08:00
Merge pull request #761 from PowerShell/andschwa/cli
Switch dotnet publish for dotnet build (and more)
This commit is contained in:
commit
b7a7d8f048
11
.gitmodules
vendored
11
.gitmodules
vendored
@ -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
|
||||
|
17
.travis.yml
17
.travis.yml
@ -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=
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
17
appveyor.yml
17
appveyor.yml
@ -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
|
||||
|
20
bootstrap.sh
Executable file
20
bootstrap.sh
Executable file
@ -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
|
2
build.sh
2
build.sh
@ -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
|
||||
|
23
mapping.json
23
mapping.json
@ -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"
|
||||
}
|
||||
|
12
pester.sh
12
pester.sh
@ -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
|
@ -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'
|
||||
}
|
@ -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": {
|
||||
}
|
||||
|
@ -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'
|
||||
}
|
@ -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;
|
@ -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": { }
|
||||
}
|
||||
}
|
@ -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,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
|
BIN
src/Modules/AppxProvider/AppxProvider.Resource.psd1
Normal file
BIN
src/Modules/AppxProvider/AppxProvider.Resource.psd1
Normal file
Binary file not shown.
BIN
src/Modules/AppxProvider/AppxProvider.psd1
Normal file
BIN
src/Modules/AppxProvider/AppxProvider.psd1
Normal file
Binary file not shown.
956
src/Modules/AppxProvider/AppxProvider.psm1
Normal file
956
src/Modules/AppxProvider/AppxProvider.psm1
Normal file
@ -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
|
BIN
src/Modules/Microsoft.PowerShell.Archive/ArchiveResources.psd1
Normal file
BIN
src/Modules/Microsoft.PowerShell.Archive/ArchiveResources.psd1
Normal file
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'
|
||||
}
|
BIN
src/Modules/PSDiagnostics/PSDiagnostics.psd1
Normal file
BIN
src/Modules/PSDiagnostics/PSDiagnostics.psd1
Normal file
Binary file not shown.
BIN
src/Modules/PSDiagnostics/PSDiagnostics.psm1
Normal file
BIN
src/Modules/PSDiagnostics/PSDiagnostics.psm1
Normal file
Binary file not shown.
202
src/Modules/PSGet/PSGet.Format.ps1xml
Normal file
202
src/Modules/PSGet/PSGet.Format.ps1xml
Normal file
@ -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>
|
BIN
src/Modules/PSGet/PSGet.Resource.psd1
Normal file
BIN
src/Modules/PSGet/PSGet.Resource.psd1
Normal file
Binary file not shown.
BIN
src/Modules/PSGet/PSGet.psd1
Normal file
BIN
src/Modules/PSGet/PSGet.psd1
Normal file
Binary file not shown.
13064
src/Modules/PSGet/PSModule.psm1
Normal file
13064
src/Modules/PSGet/PSModule.psm1
Normal file
File diff suppressed because it is too large
Load Diff
@ -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": { }
|
||||
}
|
||||
}
|
||||
|
@ -1 +0,0 @@
|
||||
Subproject commit 4bb241ad11c54985617343fbeb8700cfdcdf7ae0
|
12
src/libpsl-native/.gitignore
vendored
Normal file
12
src/libpsl-native/.gitignore
vendored
Normal file
@ -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
|
10
src/libpsl-native/CMakeLists.txt
Normal file
10
src/libpsl-native/CMakeLists.txt
Normal file
@ -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)
|
56
src/libpsl-native/README.md
Normal file
56
src/libpsl-native/README.md
Normal file
@ -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
|
14
src/libpsl-native/src/CMakeLists.txt
Normal file
14
src/libpsl-native/src/CMakeLists.txt
Normal file
@ -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})
|
115
src/libpsl-native/src/createhardlink.cpp
Normal file
115
src/libpsl-native/src/createhardlink.cpp
Normal file
@ -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;
|
||||
}
|
9
src/libpsl-native/src/createhardlink.h
Normal file
9
src/libpsl-native/src/createhardlink.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
int32_t CreateHardLink(const char *link, const char *target);
|
||||
|
||||
PAL_END_EXTERNC
|
106
src/libpsl-native/src/createsymlink.cpp
Normal file
106
src/libpsl-native/src/createsymlink.cpp
Normal file
@ -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;
|
||||
}
|
9
src/libpsl-native/src/createsymlink.h
Normal file
9
src/libpsl-native/src/createsymlink.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
int32_t CreateSymLink(const char *link, const char *target);
|
||||
|
||||
PAL_END_EXTERNC
|
90
src/libpsl-native/src/followsymlink.cpp
Normal file
90
src/libpsl-native/src/followsymlink.cpp
Normal file
@ -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);
|
||||
}
|
9
src/libpsl-native/src/followsymlink.h
Normal file
9
src/libpsl-native/src/followsymlink.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
char* FollowSymLink(const char* fileName);
|
||||
|
||||
PAL_END_EXTERNC
|
45
src/libpsl-native/src/getcomputername.cpp
Normal file
45
src/libpsl-native/src/getcomputername.cpp
Normal file
@ -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());
|
||||
}
|
9
src/libpsl-native/src/getcomputername.h
Normal file
9
src/libpsl-native/src/getcomputername.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
char *GetComputerName();
|
||||
|
||||
PAL_END_EXTERNC
|
9
src/libpsl-native/src/getcurrentprocessorid.cpp
Normal file
9
src/libpsl-native/src/getcurrentprocessorid.cpp
Normal file
@ -0,0 +1,9 @@
|
||||
#include "getcurrentprocessorid.h"
|
||||
#include <unistd.h>
|
||||
|
||||
int32_t GetCurrentProcessId()
|
||||
{
|
||||
pid_t pid = getpid();
|
||||
return static_cast<int32_t>(pid);
|
||||
}
|
||||
|
10
src/libpsl-native/src/getcurrentprocessorid.h
Normal file
10
src/libpsl-native/src/getcurrentprocessorid.h
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
int32_t GetCurrentProcessId();
|
||||
|
||||
PAL_END_EXTERNC
|
||||
|
9
src/libpsl-native/src/getcurrentthreadid.cpp
Normal file
9
src/libpsl-native/src/getcurrentthreadid.cpp
Normal file
@ -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);
|
||||
}
|
10
src/libpsl-native/src/getcurrentthreadid.h
Normal file
10
src/libpsl-native/src/getcurrentthreadid.h
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
HANDLE GetCurrentThreadId();
|
||||
|
||||
PAL_END_EXTERNC
|
||||
|
64
src/libpsl-native/src/getfullyqualifiedname.cpp
Normal file
64
src/libpsl-native/src/getfullyqualifiedname.cpp
Normal file
@ -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;
|
||||
}
|
9
src/libpsl-native/src/getfullyqualifiedname.h
Normal file
9
src/libpsl-native/src/getfullyqualifiedname.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
char *GetFullyQualifiedName();
|
||||
|
||||
PAL_END_EXTERNC
|
104
src/libpsl-native/src/getlinkcount.cpp
Normal file
104
src/libpsl-native/src/getlinkcount.cpp
Normal file
@ -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;
|
||||
}
|
9
src/libpsl-native/src/getlinkcount.h
Normal file
9
src/libpsl-native/src/getlinkcount.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
int32_t GetLinkCount(const char* fileName, int32_t *count);
|
||||
|
||||
PAL_END_EXTERNC
|
65
src/libpsl-native/src/getusername.cpp
Normal file
65
src/libpsl-native/src/getusername.cpp
Normal file
@ -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);
|
||||
}
|
9
src/libpsl-native/src/getusername.h
Normal file
9
src/libpsl-native/src/getusername.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
char* GetUserName();
|
||||
|
||||
PAL_END_EXTERNC
|
81
src/libpsl-native/src/isexecutable.cpp
Normal file
81
src/libpsl-native/src/isexecutable.cpp
Normal file
@ -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;
|
||||
}
|
9
src/libpsl-native/src/isexecutable.h
Normal file
9
src/libpsl-native/src/isexecutable.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
int32_t IsExecutable(const char* fileName);
|
||||
|
||||
PAL_END_EXTERNC
|
96
src/libpsl-native/src/issymlink.cpp
Normal file
96
src/libpsl-native/src/issymlink.cpp
Normal file
@ -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;
|
||||
}
|
9
src/libpsl-native/src/issymlink.h
Normal file
9
src/libpsl-native/src/issymlink.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
int32_t IsSymLink(const char* fileName);
|
||||
|
||||
PAL_END_EXTERNC
|
45
src/libpsl-native/src/pal.h
Normal file
45
src/libpsl-native/src/pal.h
Normal file
@ -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
|
||||
|
73
src/libpsl-native/src/setdate.cpp
Normal file
73
src/libpsl-native/src/setdate.cpp
Normal file
@ -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;
|
||||
}
|
22
src/libpsl-native/src/setdate.h
Normal file
22
src/libpsl-native/src/setdate.h
Normal file
@ -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
|
22
src/libpsl-native/test/CMakeLists.txt
Normal file
22
src/libpsl-native/test/CMakeLists.txt
Normal file
@ -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)
|
1
src/libpsl-native/test/googletest
Submodule
1
src/libpsl-native/test/googletest
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit c99458533a9b4c743ed51537e25989ea55944908
|
7
src/libpsl-native/test/main.cpp
Normal file
7
src/libpsl-native/test/main.cpp
Normal file
@ -0,0 +1,7 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
91
src/libpsl-native/test/test-createhardlink.cpp
Normal file
91
src/libpsl-native/test/test-createhardlink.cpp
Normal file
@ -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);
|
||||
}
|
||||
|
117
src/libpsl-native/test/test-createsymlink.cpp
Normal file
117
src/libpsl-native/test/test-createsymlink.cpp
Normal file
@ -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);
|
||||
}
|
33
src/libpsl-native/test/test-getcomputername.cpp
Normal file
33
src/libpsl-native/test/test-getcomputername.cpp
Normal file
@ -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);
|
||||
}
|
16
src/libpsl-native/test/test-getcurrentprocessid.cpp
Normal file
16
src/libpsl-native/test/test-getcurrentprocessid.cpp
Normal file
@ -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));
|
||||
}
|
||||
|
16
src/libpsl-native/test/test-getcurrentthreadid.cpp
Normal file
16
src/libpsl-native/test/test-getcurrentthreadid.cpp
Normal file
@ -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));
|
||||
}
|
||||
|
40
src/libpsl-native/test/test-getfullyqualifiedname.cpp
Normal file
40
src/libpsl-native/test/test-getfullyqualifiedname.cpp
Normal file
@ -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);
|
||||
}
|
95
src/libpsl-native/test/test-getlinkcount.cpp
Normal file
95
src/libpsl-native/test/test-getlinkcount.cpp
Normal file
@ -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);
|
||||
}
|
||||
|
17
src/libpsl-native/test/test-getusername.cpp
Normal file
17
src/libpsl-native/test/test-getusername.cpp
Normal file
@ -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));
|
||||
}
|
94
src/libpsl-native/test/test-isexecutable.cpp
Normal file
94
src/libpsl-native/test/test-isexecutable.cpp
Normal file
@ -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);
|
||||
}
|
104
src/libpsl-native/test/test-issymlink.cpp
Normal file
104
src/libpsl-native/test/test-issymlink.cpp
Normal file
@ -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);
|
||||
}
|
||||
|
21
src/libpsl-native/test/test-locale.cpp
Normal file
21
src/libpsl-native/test/test-locale.cpp
Normal file
@ -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
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user