1 #!powershell
2 
3 # Copyright: (c) 2019, Micah Hunsberger
4 # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
5 
6 #AnsibleRequires -CSharpUtil Ansible.Basic
7 
8 Set-StrictMode -Version 2
9 
10 $spec = @{
11     options = @{
12         path = @{ type = 'path'; required = $true }
13         state = @{ type = 'str'; default = 'present'; choices = 'absent', 'present' }
14         recurse = @{ type = 'bool'; default = $false }
15         force = @{ type = 'bool'; default = $true }
16     }
17     supports_check_mode = $true
18 }
19 
20 $module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
21 
22 $path = $module.Params.path
23 $state = $module.Params.state
24 $recurse = $module.Params.recurse
25 $force = $module.Params.force
26 
27 $module.Result.rc = 0
28 
29 if(-not (Test-Path -LiteralPath $path)) {
30     $module.FailJson("Path to item, $path, does not exist.")
31 }
32 
33 $item = Get-Item -LiteralPath $path -Force  # Use -Force for hidden files
34 if (-not $item.PSIsContainer -and $recurse) {
35     $module.Warn("The recurse option has no effect when path is not a folder.")
36 }
37 
38 $cim_params = @{
39     ClassName = 'Win32_LogicalDisk'
=()40     Filter = "DeviceId='$($item.PSDrive.Name):'"
41     Property = @('FileSystem', 'SupportsFileBasedCompression')
42 }
43 $drive_info = Get-CimInstance @cim_params
44 if ($drive_info.SupportsFileBasedCompression -eq $false) {
45     $module.FailJson("Path, $path, is not on a filesystemi '$($drive_info.FileSystem)' that supports file based compression.")
46 }
47 
Get-ReturnCodeMessage()48 function Get-ReturnCodeMessage {
49     param(
50         [int]$code
51     )
52     switch ($code) {
53         0 { return "The request was successful." }
54         2 { return "Access was denied." }
55         8 { return "An unspecified failure occurred." }
56         9 { return "The name specified was not valid." }
57         10 { return "The object specified already exists." }
58         11 { return "The file system is not NTFS." }
59         12 { return "The platform is not Windows." }
60         13 { return "The drive is not the same." }
61         14 { return "The directory is not empty." }
62         15 { return "There has been a sharing violation." }
63         16 { return "The start file specified was not valid." }
64         17 { return "A privilege required for the operation is not held." }
65         21 { return "A parameter specified is not valid." }
66     }
67 }
68 
Get-EscapedFileNamenull69 function Get-EscapedFileName {
70     param(
71         [string]$FullName
72     )
73     return $FullName.Replace("\","\\").Replace("'","\'")
74 }
75 
76 $is_compressed = ($item.Attributes -band [System.IO.FileAttributes]::Compressed) -eq [System.IO.FileAttributes]::Compressed
77 $needs_changed = $is_compressed -ne ($state -eq 'present')
78 
79 if($force -and $recurse -and $item.PSIsContainer) {
80     if (-not $needs_changed) {
81         # Check the subfolders and files
82         $entries_to_check = $item.EnumerateFileSystemInfos("*", [System.IO.SearchOption]::AllDirectories)
83         foreach ($entry in $entries_to_check) {
84             $is_compressed = ($entry.Attributes -band [System.IO.FileAttributes]::Compressed) -eq [System.IO.FileAttributes]::Compressed
85             if ($is_compressed -ne ($state -eq 'present')) {
86                 $needs_changed = $true
87                 break
88             }
89         }
90     }
91 }
92 
93 if($needs_changed) {
94     $module.Result.changed = $true
95     if ($item.PSIsContainer) {
96         $cim_obj = Get-CimInstance -ClassName 'Win32_Directory' -Filter "Name='$(Get-EscapedFileName -FullName $item.FullName)'"
97     } else {
98         $cim_obj = Get-CimInstance -ClassName 'CIM_LogicalFile' -Filter "Name='$(Get-EscapedFileName -FullName $item.FullName)'"
99     }
100     if($state -eq 'present') {
101         if(-not $module.CheckMode) {
102             $ret = Invoke-CimMethod -InputObject $cim_obj -MethodName 'CompressEx' -Arguments @{ Recursive = $recurse }
103             $module.Result.rc = $ret.ReturnValue
104         }
105     } else {
106         if(-not $module.CheckMode) {
107             $ret = $ret = Invoke-CimMethod -InputObject $cim_obj -MethodName 'UnCompressEx' -Arguments @{ Recursive = $recurse }
108             $module.Result.rc = $ret.ReturnValue
109         }
110     }
111 }
112 
113 $module.Result.msg = Get-ReturnCodeMessage -code $module.Result.rc
114 if($module.Result.rc -ne 0) {
115     $module.FailJson($module.Result.msg)
116 }
117 
118 $module.ExitJson()
119