1
+ function Test-SystemPath {
2
+ <#
3
+ . SYNOPSIS
4
+ Tests if a given path is a system directory that should be protected from bulk deletion.
5
+ . DESCRIPTION
6
+ This function checks if the specified path matches known system directories that should not be processed
7
+ by Remove-StaleFiles for safety reasons. It checks against Windows system paths (drive roots, Program Files,
8
+ Windows directory) and Unix/Linux system paths (/, /etc, /bin, etc.).
9
+ . PARAMETER TestPath
10
+ The path to test for system directory status.
11
+ . OUTPUTS
12
+ [bool] Returns $true if the path is a system directory, $false otherwise.
13
+ #>
14
+ param (
15
+ [string ] $TestPath
16
+ )
17
+
18
+ # Resolve to absolute path.
19
+ $FullPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath ($TestPath )
20
+
21
+ # Get blocked paths using system variables where available.
22
+ $BlockedPaths = @ ()
23
+
24
+ # Windows system paths
25
+ if ($IsWindows -or $env: OS -eq ' Windows_NT' ) {
26
+ # Drive roots (C:\, D:\, etc.).
27
+ $BlockedPaths += Get-PSDrive - PSProvider FileSystem | ForEach-Object { $_.Root }
28
+
29
+ # System directories using environment variables.
30
+ if ($env: SystemRoot ) { $BlockedPaths += $env: SystemRoot }
31
+ if ($env: ProgramFiles ) { $BlockedPaths += $env: ProgramFiles }
32
+ if ($env: ProgramData ) { $BlockedPaths += $env: ProgramData }
33
+ if ($env: ProgramW6432 ) { $BlockedPaths += $env: ProgramW6432 }
34
+ if (${env: ProgramFiles(x86)} ) { $BlockedPaths += ${env: ProgramFiles(x86)} }
35
+
36
+ # .NET system directory.
37
+ try {
38
+ $BlockedPaths += [Environment ]::SystemDirectory
39
+ } catch { }
40
+ }
41
+
42
+ # Unix/Linux system paths.
43
+ if ($IsLinux -or $IsMacOS -or (! $IsWindows -and $env: OS -ne ' Windows_NT' )) {
44
+ $BlockedPaths += @ (
45
+ ' /' ,
46
+ ' /etc' ,
47
+ ' /bin' ,
48
+ ' /sbin' ,
49
+ ' /usr' ,
50
+ ' /boot' ,
51
+ ' /sys' ,
52
+ ' /proc'
53
+ )
54
+ }
55
+
56
+ # macOS additional paths.
57
+ if ($IsMacOS ) {
58
+ $BlockedPaths += @ (
59
+ ' /System' ,
60
+ ' /Applications'
61
+ )
62
+ }
63
+
64
+ # Check if the test path matches or is a parent of any blocked path.
65
+ foreach ($BlockedPath in $BlockedPaths ) {
66
+ if (-not $BlockedPath ) { continue }
67
+
68
+ try {
69
+ $ResolvedBlockedPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath ($BlockedPath )
70
+
71
+ # Normalise paths for comparison (handle trailing separators).
72
+ $NormalisedTestPath = $FullPath.TrimEnd ([System.IO.Path ]::DirectorySeparatorChar, [System.IO.Path ]::AltDirectorySeparatorChar)
73
+ $NormalisedBlockedPath = $ResolvedBlockedPath.TrimEnd ([System.IO.Path ]::DirectorySeparatorChar, [System.IO.Path ]::AltDirectorySeparatorChar)
74
+
75
+ # Check for exact match.
76
+ if ($NormalisedTestPath -eq $NormalisedBlockedPath ) {
77
+ return $true
78
+ }
79
+ }
80
+ catch {
81
+ # If path resolution fails, skip this check.
82
+ continue
83
+ }
84
+ }
85
+
86
+ return $false
87
+ }
88
+
1
89
function Remove-StaleFiles {
2
90
<#
3
91
. SYNOPSIS
@@ -58,102 +146,27 @@ function Remove-StaleFiles {
58
146
$StartTime = Get-Date
59
147
60
148
# Set up logging - use appropriate temp directory for the platform.
61
- $TempDir = [System.IO.Path ]::GetTempPath()
62
- $LogDir = Join-Path $TempDir ' PSF-Module/Logs'
63
- $LogName = ' RemoveStaleFiles'
149
+ $TempDirectory = [System.IO.Path ]::GetTempPath()
150
+ $LogDirectory = Join-Path $TempDirectory ' PSF-Module/Logs'
151
+ $LogFileName = ' RemoveStaleFiles'
64
152
$DateSuffix = Get-Date - Format ' yyyy-MM-dd'
65
- $LogPath = Join-Path $LogDir (' {0}-{1}.log' -f $LogName , $DateSuffix )
153
+ $LogPath = Join-Path $LogDirectory (' {0}-{1}.log' -f $LogFileName , $DateSuffix )
66
154
67
155
function Write-StaleFileLog {
68
156
param (
69
157
[string ] $Message ,
70
158
[string ] $Level = ' INFO'
71
159
)
72
160
73
- if (-not (Test-Path $LogDir )) {
74
- $null = New-Item - Path $LogDir - ItemType Directory - Force
161
+ if (-not (Test-Path $LogDirectory )) {
162
+ $null = New-Item - Path $LogDirectory - ItemType Directory - Force
75
163
}
76
164
77
- $Timestamp = Get-Date - Format ' yyyy-MM-dd HH:mm:ss'
78
- $LogEntry = ' {0} [{1}] {2}' -f $Timestamp , $Level , $Message
79
- $LogEntry | Out-File - FilePath $LogPath - Append - Encoding UTF8
165
+ $TimeStamp = Get-Date - Format ' yyyy-MM-dd HH:mm:ss'
166
+ $LogEntry = ' {0} [{1}] {2}' -f $TimeStamp , $Level , $Message
167
+ $null = $ LogEntry | Out-File - FilePath $LogPath - Append - Encoding UTF8
80
168
}
81
169
82
- function Test-SystemPath {
83
- param (
84
- [string ] $TestPath
85
- )
86
-
87
- # Resolve to absolute path.
88
- $FullPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath ($TestPath )
89
-
90
- # Get blocked paths using system variables where available.
91
- $BlockedPaths = @ ()
92
-
93
- # Windows system paths
94
- if ($IsWindows -or $env: OS -eq ' Windows_NT' ) {
95
- # Drive roots (C:\, D:\, etc.).
96
- $BlockedPaths += Get-PSDrive - PSProvider FileSystem | ForEach-Object { $_.Root }
97
-
98
- # System directories using environment variables.
99
- if ($env: SystemRoot ) { $BlockedPaths += $env: SystemRoot }
100
- if ($env: ProgramFiles ) { $BlockedPaths += $env: ProgramFiles }
101
- if ($env: ProgramData ) { $BlockedPaths += $env: ProgramData }
102
- if ($env: ProgramW6432 ) { $BlockedPaths += $env: ProgramW6432 }
103
- if (${env: ProgramFiles(x86)} ) { $BlockedPaths += ${env: ProgramFiles(x86)} }
104
-
105
- # .NET system directory.
106
- try {
107
- $BlockedPaths += [Environment ]::SystemDirectory
108
- } catch { }
109
- }
110
-
111
- # Unix/Linux system paths.
112
- if ($IsLinux -or $IsMacOS -or (! $IsWindows -and $env: OS -ne ' Windows_NT' )) {
113
- $BlockedPaths += @ (
114
- ' /' ,
115
- ' /etc' ,
116
- ' /bin' ,
117
- ' /sbin' ,
118
- ' /usr' ,
119
- ' /boot' ,
120
- ' /sys' ,
121
- ' /proc'
122
- )
123
- }
124
-
125
- # macOS additional paths.
126
- if ($IsMacOS ) {
127
- $BlockedPaths += @ (
128
- ' /System' ,
129
- ' /Applications'
130
- )
131
- }
132
-
133
- # Check if the test path matches or is a parent of any blocked path.
134
- foreach ($BlockedPath in $BlockedPaths ) {
135
- if (-not $BlockedPath ) { continue }
136
-
137
- try {
138
- $ResolvedBlockedPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath ($BlockedPath )
139
-
140
- # Normalize paths for comparison (handle trailing separators).
141
- $NormalizedTestPath = $FullPath.TrimEnd ([System.IO.Path ]::DirectorySeparatorChar, [System.IO.Path ]::AltDirectorySeparatorChar)
142
- $NormalizedBlockedPath = $ResolvedBlockedPath.TrimEnd ([System.IO.Path ]::DirectorySeparatorChar, [System.IO.Path ]::AltDirectorySeparatorChar)
143
-
144
- # Check for exact match.
145
- if ($NormalizedTestPath -eq $NormalizedBlockedPath ) {
146
- return $true
147
- }
148
- }
149
- catch {
150
- # If path resolution fails, skip this check.
151
- continue
152
- }
153
- }
154
-
155
- return $false
156
- }
157
170
158
171
function Clear-OldLogs {
159
172
param (
@@ -164,7 +177,7 @@ function Remove-StaleFiles {
164
177
165
178
if (Test-Path $LogDirectory ) {
166
179
$CutoffDate = (Get-Date ).AddDays(- $RetentionDays )
167
- Get-ChildItem - Path $LogDirectory - Filter (' {0}-*.log' -f $LogPrefix ) |
180
+ $null = Get-ChildItem - Path $LogDirectory - Filter (' {0}-*.log' -f $LogPrefix ) |
168
181
Where-Object { $_.LastWriteTime -lt $CutoffDate } |
169
182
ForEach-Object {
170
183
try {
@@ -179,7 +192,7 @@ function Remove-StaleFiles {
179
192
}
180
193
181
194
# Clean up old logs.
182
- Clear-OldLogs - LogDirectory $LogDir - LogPrefix $LogName - RetentionDays $LogRetentionDays
195
+ Clear-OldLogs - LogDirectory $LogDirectory - LogPrefix $LogFileName - RetentionDays $LogRetentionDays
183
196
184
197
# Log function start.
185
198
$LogParams = @ (
@@ -264,14 +277,14 @@ function Remove-StaleFiles {
264
277
if ($Files.Count -gt 0 ) {
265
278
Write-Information (' Files: {0}' -f $Files.Count )
266
279
if ($VerbosePreference -eq ' Continue' ) {
267
- $Files | ForEach-Object { Write-Verbose (' {0} ({1})' -f $_.FullName , (Get-Date $_.LastWriteTime - Format ' yyyy-MM-dd HH:mm:ss' )) }
280
+ $null = $ Files | ForEach-Object { Write-Verbose (' {0} ({1})' -f $_.FullName , (Get-Date $_.LastWriteTime - Format ' yyyy-MM-dd HH:mm:ss' )) }
268
281
}
269
282
}
270
283
271
284
if ($Directories.Count -gt 0 ) {
272
285
Write-Information (' Directories: {0}' -f $Directories.Count )
273
286
if ($VerbosePreference -eq ' Continue' ) {
274
- $Directories | ForEach-Object { Write-Verbose (' {0} ({1})' -f $_.FullName , (Get-Date $_.LastWriteTime - Format ' yyyy-MM-dd HH:mm:ss' )) }
287
+ $null = $ Directories | ForEach-Object { Write-Verbose (' {0} ({1})' -f $_.FullName , (Get-Date $_.LastWriteTime - Format ' yyyy-MM-dd HH:mm:ss' )) }
275
288
}
276
289
}
277
290
0 commit comments