From 5abf64d7c55945ce47b7f7cb3b9d4ebd65b6f239 Mon Sep 17 00:00:00 2001
From: Mioki <22417711+okibcn@users.noreply.github.com>
Date: Fri, 3 Feb 2023 12:10:42 -0800
Subject: [PATCH] Added Module folder

---
 WslCompact/WslCompact.psd1 | 131 +++++++++++++++++++++++++++++++++++++
 WslCompact/WslCompact.psm1 | 127 +++++++++++++++++++++++++++++++++++
 2 files changed, 258 insertions(+)
 create mode 100644 WslCompact/WslCompact.psd1
 create mode 100644 WslCompact/WslCompact.psm1

diff --git a/WslCompact/WslCompact.psd1 b/WslCompact/WslCompact.psd1
new file mode 100644
index 0000000..73226a8
--- /dev/null
+++ b/WslCompact/WslCompact.psd1
@@ -0,0 +1,131 @@
+#
+# Module manifest for module 'WslCompact'
+#
+# Generated by: Oscar Lopez
+#
+# Generated on: 2023-02-02
+#
+
+@{
+
+# Script module or binary module file associated with this manifest.
+RootModule = 'WslCompact.psm1'
+
+# Version number of this module.
+ModuleVersion = '6.0'
+
+# Supported PSEditions
+# CompatiblePSEditions = @()
+
+# ID used to uniquely identify this module
+GUID = '3169a4cc-3870-4ea2-a4b6-64156c107797'
+
+# Author of this module
+Author = 'Oscar Lopez'
+
+# Company or vendor of this module
+CompanyName = 'Unknown'
+
+# Copyright statement for this module
+Copyright = '(c) Oscar Lopez. All rights reserved.'
+
+# Description of the functionality provided by this module
+Description = 'Compacts the size of the ever-growing WSL images'
+
+# Minimum version of the PowerShell engine required by this module
+PowerShellVersion = '5.0'
+
+# Name of the PowerShell host required by this module
+# PowerShellHostName = ''
+
+# Minimum version of the PowerShell host required by this module
+# PowerShellHostVersion = ''
+
+# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
+# DotNetFrameworkVersion = ''
+
+# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
+# ClrVersion = ''
+
+# Processor architecture (None, X86, Amd64) required by this module
+# ProcessorArchitecture = ''
+
+# Modules that must be imported into the global environment prior to importing this module
+# RequiredModules = @()
+
+# Assemblies that must be loaded prior to importing this module
+# RequiredAssemblies = @()
+
+# Script files (.ps1) that are run in the caller's environment prior to importing this module.
+# ScriptsToProcess = @()
+
+# Type files (.ps1xml) to be loaded when importing this module
+# TypesToProcess = @()
+
+# Format files (.ps1xml) to be loaded when importing this module
+# FormatsToProcess = @()
+
+# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
+# NestedModules = @()
+
+# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
+FunctionsToExport = 'WslCompact'
+
+# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
+CmdletsToExport = '*'
+
+# Variables to export from this module
+VariablesToExport = '*'
+
+# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
+AliasesToExport = '*'
+
+# DSC resources to export from this module
+# DscResourcesToExport = @()
+
+# List of all modules packaged with this module
+# ModuleList = @()
+
+# List of all files packaged with this module
+# FileList = @()
+
+# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
+PrivateData = @{
+
+    PSData = @{
+
+        # Tags applied to this module. These help with module discovery in online galleries.
+        # Tags = @()
+
+        # A URL to the license for this module.
+          LicenseUri = 'https://github.com/okibcn/wslcompact/blob/main/LICENSE'
+
+        # A URL to the main website for this project.
+          ProjectUri = 'https://github.com/okibcn/wslcompact'
+
+        # A URL to an icon representing this module.
+        # IconUri = ''
+
+        # ReleaseNotes of this module
+        # ReleaseNotes = ''
+
+        # Prerelease string of this module
+        # Prerelease = ''
+
+        # Flag to indicate whether the module requires explicit user acceptance for install/update/save
+        # RequireLicenseAcceptance = $false
+
+        # External dependent modules of this module
+        # ExternalModuleDependencies = @()
+
+    } # End of PSData hashtable
+
+} # End of PrivateData hashtable
+
+# HelpInfo URI of this module
+# HelpInfoURI = ''
+
+# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
+# DefaultCommandPrefix = ''
+
+}
diff --git a/WslCompact/WslCompact.psm1 b/WslCompact/WslCompact.psm1
new file mode 100644
index 0000000..8fa5c91
--- /dev/null
+++ b/WslCompact/WslCompact.psm1
@@ -0,0 +1,127 @@
+#  WSL compact v6.0 2023.02.03
+#  (C) 2023 Oscar Lopez.
+#  For more information visit: https://github.com/okibcn/wslcompact
+#
+
+function WslCompact {
+    $sf = 1.05
+    $compact = $false
+    $data = $false
+    $force = $false
+    $help = $false
+    $target_distros = foreach ($arg in $args) {
+        if ($arg[0] -eq '-') {
+            $compact = $compact -or ("Cc" -match $arg[1])
+            $data = $data -or ("Dd" -match $arg[1])
+            $force = $force -or ("Yy" -match $arg[1])
+            $help = $help -or ("Hh" -match $arg[1])
+        }
+        else {
+            $arg
+        }
+    }
+    Write-Host " WSL compact v6.0 2023.02.03
+ (C) 2023 Oscar Lopez
+ wslcompact -h for help. For more information visit: https://github.com/okibcn/wslcompact"
+
+    if ($help) {
+        Write-Host "
+
+ Usage: wslcompact [OPTIONS] [DISTROS]
+
+ wslcompact compacts the images of WSL distros by removing unsused space.
+ If no option is provided, it will default to info mode, without modifying any image.
+ If no distro is provided it will process all the installed images.
+ NOTE: WSL will be shutdown for compacting the images.
+
+ Options:
+  no opt. Provides distro name, path, size, and estimated new size information.
+     -c   Compacting mode: process the selected distros compacting the images.
+     -y   replaces selected images without asking for confirmation.
+     -d   Enable the processing of data images. Default is disabled.
+     -h   Prints this help
+
+ Examples:
+     wslcompact
+     wslcompact -c -d
+     wslcompact -c -y Ubuntu Kali
+    "
+        return
+    }
+    $wsl_version = (wsl --version)[0].split(' ')[-1]
+    if ($wsl_version -lt "1.0") {
+        Write-Host "
+ WARNING: 
+     your are using wsl version $wsl_version. wslcompact requires WSL version 1.0.0 or higher. 
+     You can update WSL typing: wsl --update in PowerShell or using the Microsoft Store.
+ 
+"
+        return
+    }
+    $tmp_folder = "$Env:TEMP\wslcompact"
+    $freedisk = (Get-PSDrive $env:TEMP[0]).free
+    mkdir "$tmp_folder" -ErrorAction SilentlyContinue | Out-Null
+    Get-ChildItem HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss\`{* | ForEach-Object {
+        $wsl_ = Get-ItemProperty $_.PSPath
+        $wsl_distro = $wsl_.DistributionName
+        $wsl_path = if ($wsl_.BasePath.StartsWith('\\')) { $wsl_.BasePath.Substring(4) } else { $wsl_.BasePath }
+        if ( !$target_distros -or ($wsl_distro -in $target_distros) ) {
+            # The wsl_distro is marked for processing
+            $size1 = (Get-Item -Path "$wsl_path\ext4.vhdx").Length / 1MB
+            Write-Host "`n Distro's name:  $wsl_distro"
+            Write-Host " Image file:     $wsl_path\ext4.vhdx"
+            Write-Host " Current size:   $size1 MB"
+            if ("$wsl_distro" -match "data") {
+                Write-Host " The image is not a WSL OS, but a data partition. No size estimation is available at this time."
+                $estimated = [long]($size1)
+            }
+            else {
+                $estimated = ((wsl --system -d "$wsl_distro" -e df /mnt/wslg/distro)[1] -split '\s+')[2]
+                $estimated = [long]($estimated / 1024)
+                Write-Host " Estimated size: $([long]($estimated * ((($sf - 1) / 2) + 1))) +/- $([long]($estimated * ($sf - 1) / 2)) MB"
+                Write-Host " The estimated process time using an SSD is about $([math]::ceiling($estimated/4000)) minutes."
+            }
+            if (($estimated * $sf) -lt ($freedisk / 1MB)) {
+                # There is enough free space in the TEMP drive or a data image.
+                if ($compact) {
+                    # we are in compact mode, we process the image.
+                    if ((!$data) -and ("$wsl_distro" -match "data")) {
+                        Write-Host " Bypassing data image. use -d option to force processing of data images."
+                        Continue
+                    }
+                    Write-Host " NOTE: You can safely cancel at any time by pressing Ctrl-C`n " -NoNewLine
+                    remove-item "$tmp_folder/*" -Recurse -Force
+                    wsl --shutdown
+                    cmd /c "wsl --export ""$wsl_distro"" - | wsl --import wslclean ""$tmp_folder"" -"
+                    wsl --shutdown
+                    if (Test-Path "$tmp_folder/ext4.vhdx") {
+                        Move-Item "$tmp_folder/ext4.vhdx" "$tmp_folder/$wsl_distro.vhdx" -Force
+                        wsl --unregister wslclean | Out-Null
+                        $size2 = (Get-Item -Path "$tmp_folder/$wsl_distro.vhdx").Length / 1MB
+                        Write-Host " New Image compacted from $size1 MB to $size2 MB"
+                        $answer = if ($force) { 'y' } else { read-host -prompt " Do you want to apply changes and use the new image (y/N)" }
+                        if ($answer -match 'y') {
+                            Move-Item "$tmp_folder/$wsl_distro.vhdx" "$wsl_path/ext4.vhdx" -Force
+                            Write-Host " Image replaced for distro: $wsl_distro"
+                        }
+                    }
+                    else {
+                        Write-Host " WARNING: wslcompact found errors in the current image. It could be a storage problem,"
+                        Write-Host "          a corrupted ext4 filesystem, or any other issue. Image not processed."
+                    }
+                }
+            }
+            else {
+                # There isn't enough free space in the TEMP drive
+                write-Host " WARNING: there isn't enough free space in temp drive"(Get-PSDrive $env:TEMP[0])"to process $wsl_distro."
+                write-Host "          There are only $([long]($freedisk / 1MB)) MB available."
+                write-Host ""
+                write-Host " Please, change the TEMP folder to a drive with at least $([long]($estimated * $sf / 1MB)) MB of free space."
+                write-Host " You cand do it by typing `$env:TEMP=`"Z:/your/new/temp/folder`" before using wslcompact.`n"
+            }
+        }
+    }
+    Remove-Item -Recurse -Force "$tmp_folder"
+    write-Host ""
+}
+Export-ModuleMember -Function 'wslcompact'