2014-09-26 01:01:01 +00:00
#!powershell
# This file is part of Ansible
2017-11-16 00:04:03 +00:00
# Copyright (c) 2017 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
# Requires -Module Ansible.ModuleUtils.Legacy
# Requires -Module Ansible.ModuleUtils.FileUtil
2014-09-26 01:01:01 +00:00
2017-01-27 22:51:12 +00:00
# C# code to determine link target, copied from http://chrisbensen.blogspot.com.au/2010/06/getfinalpathnamebyhandle.html
$symlink_util = @"
using System ;
using System . Text ;
using Microsoft . Win32 . SafeHandles ;
using System . ComponentModel ;
using System . Runtime . InteropServices ;
namespace Ansible . Command
{
public class SymLinkHelper
{
private const int FILE_SHARE_WRITE = 2 ;
private const int CREATION_DISPOSITION_OPEN_EXISTING = 3 ;
private const int FILE_FLAG_BACKUP_SEMANTICS = 0x02000000 ;
[ DllImport ( " kernel32.dll " , EntryPoint = " GetFinalPathNameByHandleW " , CharSet = CharSet . Unicode , SetLastError = true ) ]
public static extern int GetFinalPathNameByHandle ( IntPtr handle , [ In, Out ] StringBuilder path , int bufLen , int flags ) ;
2017-02-24 06:58:51 +00:00
[ DllImport ( " kernel32.dll " , EntryPoint = " CreateFileW " , CharSet = CharSet . Unicode , SetLastError = true ) ]
public static extern SafeFileHandle CreateFile ( string lpFileName , int dwDesiredAccess ,
2017-01-27 22:51:12 +00:00
int dwShareMode , IntPtr SecurityAttributes , int dwCreationDisposition , int dwFlagsAndAttributes , IntPtr hTemplateFile ) ;
2017-02-24 06:58:51 +00:00
public static string GetSymbolicLinkTarget ( System . IO . DirectoryInfo symlink )
{
2017-01-27 22:51:12 +00:00
SafeFileHandle directoryHandle = CreateFile ( symlink . FullName , 0 , 2 , System . IntPtr . Zero , CREATION_DISPOSITION_OPEN_EXISTING , FILE_FLAG_BACKUP_SEMANTICS , System . IntPtr . Zero ) ;
if ( directoryHandle . IsInvalid )
throw new Win32Exception ( Marshal . GetLastWin32Error ( ) ) ;
StringBuilder path = new StringBuilder ( 512 ) ;
int size = GetFinalPathNameByHandle ( directoryHandle . DangerousGetHandle ( ) , path , path . Capacity , 0 ) ;
if ( size < 0 )
throw new Win32Exception ( Marshal . GetLastWin32Error ( ) ) ; / / The remarks section of GetFinalPathNameByHandle mentions the return being prefixed with " \\?\ " / / More information about " \\?\ " here - > http : / / msdn . microsoft . com / en-us / library / aa365247 ( v = VS . 85 ) . aspx
if ( path [ 0 ] = = '\\' & & path [ 1 ] = = '\\' & & path [ 2 ] = = '?' & & path [ 3 ] = = '\\' )
2017-02-24 06:58:51 +00:00
return path . ToString ( ) . Substring ( 4 ) ;
else
return path . ToString ( ) ;
2017-01-27 22:51:12 +00:00
}
}
}
" @
Add-Type -TypeDefinition $symlink_util
2014-09-26 01:01:01 +00:00
2015-06-05 13:35:26 +00:00
function Date_To_Timestamp($start_date , $end_date )
{
2016-04-20 19:26:27 +00:00
If ( $start_date -and $end_date )
{
2017-02-24 06:58:51 +00:00
return ( New-TimeSpan -Start $start_date -End $end_date ) . TotalSeconds
2016-04-20 19:26:27 +00:00
}
2015-06-05 13:35:26 +00:00
}
2017-02-24 06:58:51 +00:00
$params = Parse-Args $args -supports_check_mode $true
2014-09-26 01:01:01 +00:00
2017-02-24 06:58:51 +00:00
$path = Get-AnsibleParam -obj $params -name " path " -type " path " -failifempty $true -aliases " dest " , " name "
2017-11-27 23:58:55 +00:00
$get_md5 = Get-AnsibleParam -obj $params -name " get_md5 " -type " bool " -default $false
2017-02-24 06:58:51 +00:00
$get_checksum = Get-AnsibleParam -obj $params -name " get_checksum " -type " bool " -default $true
$checksum_algorithm = Get-AnsibleParam -obj $params -name " checksum_algorithm " -type " str " -default " sha1 " -validateset " md5 " , " sha1 " , " sha256 " , " sha384 " , " sha512 "
$result = @ {
2014-09-26 01:01:01 +00:00
changed = $false
2017-08-04 03:55:58 +00:00
stat = @ {
exists = $false
}
2017-04-03 18:38:34 +00:00
}
2014-09-26 01:01:01 +00:00
2017-11-27 23:58:55 +00:00
# get_md5 will be an undocumented option in 2.9 to be removed at a later
# date if possible (3.0+)
if ( Get-Member -inputobject $params -name " get_md5 " ) {
Add-DepreactionWarning -obj $result -message " get_md5 has been deprecated along with the md5 return value, use get_checksum=True and checksum_algorithm=md5 instead " -version 2.9
2017-02-24 06:58:51 +00:00
}
2017-11-16 00:04:03 +00:00
$info = Get-FileItem -path $path
If ( $info -ne $null )
2014-09-26 01:01:01 +00:00
{
2017-02-24 06:58:51 +00:00
$result . stat . exists = $true
# Initial values
$result . stat . isdir = $false
2017-04-03 18:38:34 +00:00
$result . stat . islnk = $false
2017-08-04 03:55:58 +00:00
$result . stat . isreg = $false
2017-02-24 06:58:51 +00:00
$result . stat . isshared = $false
2016-04-20 19:26:27 +00:00
2017-02-24 06:58:51 +00:00
$epoch_date = Get-Date -Date " 01/01/1970 "
$result . stat . creationtime = ( Date_To_Timestamp $epoch_date $info . CreationTime )
$result . stat . lastaccesstime = ( Date_To_Timestamp $epoch_date $info . LastAccessTime )
$result . stat . lastwritetime = ( Date_To_Timestamp $epoch_date $info . LastWriteTime )
$result . stat . filename = $info . Name
$result . stat . path = $info . FullName
2017-01-27 22:51:12 +00:00
$attributes = @ ( )
foreach ( $attribute in ( $info . Attributes -split ',' ) ) {
2017-04-03 18:38:34 +00:00
$attributes + = $attribute . Trim ( )
2017-01-27 22:51:12 +00:00
}
2017-02-24 06:58:51 +00:00
$result . stat . attributes = $info . Attributes . ToString ( )
$result . stat . isarchive = $attributes -contains " Archive "
$result . stat . ishidden = $attributes -contains " Hidden "
$result . stat . isreadonly = $attributes -contains " ReadOnly "
2017-01-27 22:51:12 +00:00
2016-04-20 19:26:27 +00:00
If ( $info )
{
2017-04-03 18:38:34 +00:00
$accesscontrol = $info . GetAccessControl ( )
2016-04-20 19:26:27 +00:00
}
Else
{
2017-04-03 18:38:34 +00:00
$accesscontrol = $null
2016-04-20 19:26:27 +00:00
}
2017-02-24 06:58:51 +00:00
$result . stat . owner = $accesscontrol . Owner
2017-01-27 22:51:12 +00:00
2017-02-24 06:58:51 +00:00
$iscontainer = $info . PSIsContainer
2017-01-27 22:51:12 +00:00
If ( $attributes -contains 'ReparsePoint' )
2014-09-26 01:01:01 +00:00
{
2017-01-27 22:51:12 +00:00
# TODO: Find a way to differenciate between soft and junction links
2017-04-03 18:38:34 +00:00
$result . stat . islnk = $true
2017-02-24 06:58:51 +00:00
$result . stat . isdir = $true
2017-01-27 22:51:12 +00:00
# Try and get the symlink source, can result in failure if link is broken
try {
2017-02-24 06:58:51 +00:00
$result . stat . lnk_source = [ Ansible.Command.SymLinkHelper ] :: GetSymbolicLinkTarget ( $path )
} catch {
$result . stat . lnk_source = $null
}
}
2017-01-27 22:51:12 +00:00
ElseIf ( $iscontainer )
{
2017-02-24 06:58:51 +00:00
$result . stat . isdir = $true
2017-01-27 22:51:12 +00:00
2017-02-24 06:58:51 +00:00
$share_info = Get-WmiObject -Class Win32_Share -Filter " Path=' $( $info . Fullname -replace '\\' , '\\' ) ' "
If ( $share_info -ne $null )
2017-01-27 22:51:12 +00:00
{
2017-02-24 06:58:51 +00:00
$result . stat . isshared = $true
$result . stat . sharename = $share_info . Name
2017-01-27 22:51:12 +00:00
}
2017-04-03 18:38:34 +00:00
$dir_files_sum = Get-ChildItem $info . FullName -Recurse | Measure-Object -property length -sum
2017-01-27 22:51:12 +00:00
If ( $dir_files_sum -eq $null )
{
2017-02-24 06:58:51 +00:00
$result . stat . size = 0
2017-01-27 22:51:12 +00:00
}
Else {
2017-02-24 06:58:51 +00:00
$result . stat . size = $dir_files_sum . Sum
2017-01-27 22:51:12 +00:00
}
2014-09-26 01:01:01 +00:00
}
Else
{
2017-02-24 06:58:51 +00:00
$result . stat . extension = $info . Extension
2017-08-04 03:55:58 +00:00
$result . stat . isreg = $true
$result . stat . size = $info . Length
2017-01-27 22:51:12 +00:00
If ( $get_md5 ) {
2017-08-07 02:04:42 +00:00
try {
$result . stat . md5 = Get-FileChecksum -path $path -algorithm " md5 "
} catch {
2017-11-27 23:58:55 +00:00
Fail-Json -obj $result -message " failed to get MD5 hash of file, remove get_md5 to ignore this error: $( $_ . Exception . Message ) "
2017-08-07 02:04:42 +00:00
}
2017-01-27 22:51:12 +00:00
}
If ( $get_checksum ) {
2017-08-07 02:04:42 +00:00
try {
$result . stat . checksum = Get-FileChecksum -path $path -algorithm $checksum_algorithm
} catch {
Fail-Json -obj $result -message " failed to get hash of file, set get_checksum to False to ignore this error: $( $_ . Exception . Message ) "
}
2017-01-27 22:51:12 +00:00
}
2014-09-26 01:01:01 +00:00
}
}
2017-04-03 18:38:34 +00:00
Exit-Json $result