Skip to content

Instantly share code, notes, and snippets.

@f-steff
Last active August 23, 2024 02:18
Show Gist options
  • Save f-steff/7389b7693d7d2a37cd3fa2c06454427f to your computer and use it in GitHub Desktop.
Save f-steff/7389b7693d7d2a37cd3fa2c06454427f to your computer and use it in GitHub Desktop.

BinaryFixer.ps1

Overview

BinaryFixer.ps1 is a quick script designed to overcome limitations in the converter program that is part of the CC-RX compiler from Renesas. This script addresses issues with modifying ELF files, making it possible to use CRC calculations while debugging. It also simplifies the process by eliminating the need to configure the converter from the E2Studio project properties menu.

The script searches for a known structure within approximately a +/- 512 byte range and manipulates it according to the specifications on the commandline. It supports calculation and insertions of CRC-16/KERMIT (known as CRC-16-CCITT-LSB in Renesas tools) into the input file.

Motivation

The script was created to address specific challenges in working with Renesas' tools and ELF files. By automating the process of finding and manipulating specific structures within the binary files, BinaryFixer.ps1 reduces the manual effort required and ensures consistency across projects. It is particularly useful for embedded systems developers working with Renesas compilers and tools.

The latest version of this script can always be found on this Github gist:

https://gist.github.com/f-steff/7389b7693d7d2a37cd3fa2c06454427f

Usage

Command Syntax

.\BinaryFixer.ps1 -BinaryFile <path> -SearchString <string> [-Offset <integer>]
                                                            [ [-ExtractInt <integer>] | [-CalcCRC <integer>] ]
                                                            [ [-WriteCRC_SE <integer>] [-WriteCRC_BE <integer>] ] | [-MaxCount <integer>]
                                                            [-ReplaceOriginal]
                                                            [-Verbose]
                                                            [-Help]

Parameters

  • -BinaryFile : (Required) The path to the binary input file - ELF files work nicely.
  • -SearchString : (Required) The string to search for in the binary file.
  • -Offset : (Optional) An address offset, positive or negative (default is 0).
  • -ExtractInt : (Optional) An offset for extracting two bytes, positive or negative. The UINT16 will be output to StdIo after POSITION as: 0xXXYY 0xYYXX (SE and BE respectively). [Mutually exclusive with -CalcCRC]
  • -CalcCRC : (Optional) Length from POSITION to calculate CRC-16/KERMIT (max 510 bytes). CRC will be output to StdIo after POSITION as: 0xXXYY 0xYYXX (SE and BE respectively). [Mutually exclusive with -ExtractInt]
  • -WriteCRC_SE : (Optional) Offset to write the calculated CRC (or zero) in Small Endian format. This option disables -MaxCount and saves a modified file. Can be combined with -WriteCRC_BE
  • -WriteCRC_BE : (Optional) Offset to write the calculated CRC (or zero) in Big Endian format. This option disables -MaxCount and saves a modified file. Can be combined with -WriteCRC_SE
  • -MaxCount : (Optional) Stop searching after a specified number of occurrences have been found. Ignored if -WriteCRC_SE or -WriteCRC_BE is used.
  • -ReplaceOriginal: (Optional) Replace the input file with the modified file. The original file will be preserved. Only applies if -WriteCRC_SE or -WriteCRC_BE is used.
  • -Help: (Optional) Display this help message and exit.
  • -Verbose: (Optional) Write verbose information to the console during processing.

Examples

Basic Search

Search for the string "$omething$pecial" in a binary file:

.\BinaryFixer.ps1 -BinaryFile "file.x" -SearchString '$omething$pecial'
0x0000E462
0x00010462
2

Search with Offset

Search for the string "$omething$pecial" with an offset of 10:

.\BinaryFixer.ps1 -BinaryFile "file.x" -SearchString '$omething$pecial' -Offset 10

Search with Integer Extraction

Search for "$omething$pecial" and extract a 16-bit integer 16 bytes after the found position:

.\BinaryFixer.ps1 -BinaryFile "file.x" -SearchString '$omething$pecial' -ExtractInt 16

Search for "$omething$pecial" with an offset of -20 and extract a 16-bit integer 36 bytes after the found position:

.\BinaryFixer.ps1 -BinaryFile "file.x" -SearchString '$omething$pecial' -Offset -20 -ExtractInt 36

Search with CRC Calculation and Writing

Search for "$omething$pecial" with an offset of -20, calculate CRC over the next 36 bytes, and write it in Big Endian format:

.\BinaryFixer.ps1 -BinaryFile "file.x" -SearchString '$omething$pecial' -Offset -20 -CalcCRC 36 -WriteCRC_BE 36

Replace Original File

Search for "$omething$pecial", calculate CRC, write it, and replace the original file with the modified one:

.\BinaryFixer.ps1 -BinaryFile "file.x" -SearchString '$omething$pecial' -Offset -20 -CalcCRC 36 -WriteCRC_BE 36 -ReplaceOriginal

Error Messages

  • -ExtractInt and -CalcCRC cannot be used together. Please choose one.
    This error occurs if both the -ExtractInt and -CalcCRC options are specified simultaneously. They are mutually exclusive, and you must choose one.

  • Offset must be a numeric value.
    This error occurs when the -Offset parameter is provided with a non-numeric value. Ensure that the offset is a valid integer.

  • The size of the original file and the modified file do not match. Aborting operation.
    This error occurs if the original file and the modified file differ in size when -ReplaceOriginal is used. The script aborts to prevent data loss.

Return Codes

  • 0: The script executed successfully.
  • 1: The script encountered an error. Review the error message for details.

Notes

  • The script is tailored to solve specific issues with Renesas tools and ELF files. It automates and simplifies common tasks, reducing manual effort and ensuring consistency.
  • CRC16/KERMIT is known as CRC-16-CCITT-LSB in Renesas tools.
param (
[string]$BinaryFile,
[string]$SearchString,
$Offset = 0,
$ExtractInt = $null,
$CalcCRC = $null,
$WriteCRC_SE = $null,
$WriteCRC_BE = $null,
$MaxCount = $null,
[switch]$Help = $false,
[switch]$ReplaceOriginal = $false,
[switch]$Verbose = $false,
$MaxOffset = 512
)
# Debug and output control. Remove the # to activate.
#$global:flow_Debug = $true
#$global:crc_Debug = $true
#$global:SuppressOutput_Debug = $true
if ($Help) {
Write-Host "BinaryFixer.ps1 is made to overcome a shortsighted implementation of the comverter program,"
Write-Host "which is part of the CC-RX compiler from Renesas."
Write-Host "The main problem is addresses, is that ELF files are not touched by their tools, so CRC"
Write-Host "calculations of chunks inside the output files can not easily be used while debugging."
Write-Host "This script also removes the necissity to configure the converter from the E2Studio project"
Write-Host "properties menu, as it simply searches the source for a known structure and performs it's "
Write-Host "manipulation within approximately a +/- 512 byte range from the found string."
Write-Host "Only one CRC calculation type is implemented, CRC-16/KERMIT, which the Renesas converter tool"
Write-Host "calls CRC-16-CCITT-LSB"
Write-Host ""
Write-Host "Version 0.5 2024-08-23"
Write-Host "Latest version available from https://gist.github.com/f-steff/7389b7693d7d2a37cd3fa2c06454427f"
Write-Host ""
Write-Host "Usage: .\BinarySearch.ps1 -BinaryFile <path> -SearchString <string> [-Offset <integer>]"
Write-Host " [ [-ExtractInt <integer>] | [-CalcCRC <integer>] ]"
Write-Host " [ [-WriteCRC_SE <integer>] [-WriteCRC_BE <integer>] ] | [-MaxCount <integer>]"
Write-Host " [-ReplaceOriginal]"
Write-Host " [-Verbose]"
Write-Host " [-Help]"
Write-Host "Arguments:"
Write-Host " -BinaryFile <path> : Path to the binary input file - ELF files work nicely."
Write-Host " -SearchString <string> : String to search for in the binary file"
Write-Host " -Offset <integer> : Optional address offset, positive or negative (default is 0)"
Write-Host " -ExtractInt <integer> : Optional offset for extracting two bytes, positive or negative. The UINT16 will be output to StdIo after POSITION as: 0xSE 0xBE. [Mutually exclucive to -CalcCRC] ]"
Write-Host " -CalcCRC <integer> : Optional lengt from POSITION to calculate CRC-16/KERMIT (max 510 bytes), CRC will be output to StdIO after POSITION as: 0xSE 0xBE. [Mutually exclucive to -ExtractInt] "
Write-Host " -WriteCRC_SE <integer> : Optional offset to write the calculated CRC (or zero) in Small Endian format. Will disable -MaxCount. Will save a modified file. Not exclusive."
Write-Host " -WriteCRC_BE <integer> : Optional offset to write the calculated CRC (or zero) in Big Endian format. Will disable -MaxCount. Will save a modified file. Not exclusive."
Write-Host " -MaxCount <integer> : Optional number of occurrences to find (default is unlimited). Ignored if -WriteCRC_SE or -WriteCRC_BE is used."
Write-Host " -ReplaceOriginal : Optional replace the input file with the modified file. The original file will be preserver. Only if -WriteCRC_SE or -WriteCRC_BE is used."
Write-Host " -Help : Display this help message and exit"
Write-Host " -Verbose : Write verbose information to the console during processing."
Write-Host ""
Write-Host " Note: CRC16/KERMIT is know to Renesas as CRC-16-CCITT-LSB"
Write-Host ""
Write-Host "Examples:"
Write-Host ' .\BinaryFixer.ps1 -BinaryFile file.x -SearchString ''$omething$pecial'''
Write-Host ' .\BinaryFixer.ps1 -BinaryFile file.x -SearchString ''$omething$pecial'' -Offset 10'
Write-Host ""
Write-Host "The above only outputs the POSITION in the file:"
Write-Host ' 0x0000E462'
Write-Host ' 0x00010462'
Write-Host ' 2'
Write-Host ""
Write-Host ' .\BinaryFixer.ps1 -BinaryFile file.x -SearchString ''$omething$pecial'' -ExtractInt 16'
Write-Host ' .\BinaryFixer.ps1 -BinaryFile file.x -SearchString ''$omething$pecial'' -Offset -20 -ExtractInt 36'
Write-Host ' .\BinaryFixer.ps1 -BinaryFile file.x -SearchString ''$omething$pecial'' -Offset -20 - CalcCRC 36'
Write-Host ' .\BinaryFixer.ps1 -BinaryFile file.x -SearchString ''$omething$pecial'' -Offset -20 - CalcCRC 36 -WriteCRC_BE 36'
Write-Host ' .\BinaryFixer.ps1 -BinaryFile file.x -SearchString ''$omething$pecial'' -Offset -20 - CalcCRC 36 -WriteCRC_BE 36 -ReplaceOriginal'
Write-Host ' .\BinaryFixer.ps1 -BinaryFile file.x -SearchString ''$omething$pecial'' -Offset -20 - CalcCRC 36 -WriteCRC_BE 36 -WriteCRC_SE 38 -ReplaceOriginal'
Write-Host ""
Write-Host "The above outputs the POSITION in the file and either the 16bit integer read out, or the 16bit CRC calculated (and optionally written):"
Write-Host ' 0x0000E462 0x1002 0x0210'
Write-Host ' 0x00010462 0x0400 0x0004'
Write-Host ' 2'
exit 0
}
# Validate the MaxOffset input
if (-not ([int]::TryParse($Offset, [ref]$null))) {
Write-Host "Warning: Offset must be a numeric value, but is '$Offset'. Using default of 512." -ForegroundColor Red
$MaxOffset = 512
}
$slideSize = $MaxOffset # 512 The size of each individual chunk
# Validate inputs
if (-not (Test-Path $BinaryFile)) {
Write-Host "Error: File not found: $BinaryFile" -ForegroundColor Red
exit 1
}
# Validate the search string
if ([string]::IsNullOrWhiteSpace($SearchString)) {
Write-Host "Search string cannot be empty." -ForegroundColor Red
exit 1
}
# Convert the search string to a byte array
$searchBytes = [System.Text.Encoding]::ASCII.GetBytes($SearchString)
# Validate the offset input
if (-not ([int]::TryParse($Offset, [ref]$null))) {
Write-Host "Offset must be a numeric value." -ForegroundColor Red
exit 1
}
# Check for mutually exclusive options
if ($ExtractInt -ne $null -and $CalcCRC -ne $null) {
Write-Host "Error: -ExtractInt and -CalcCRC are mutually exclusive, and cannot be used together. Please choose one." -ForegroundColor Red
exit 1
}
# Validate the ExtractInt input if provided
if ($ExtractInt -ne $null) {
try {
$ExtractInt = [int]$ExtractInt
} catch {
Write-Host "ExtractInt must be a valid integer." -ForegroundColor Red
exit 1
}
# Ensure ExtractInt is within the ±512 range
if ($ExtractInt -lt -512 -or $ExtractInt -gt 512) {
Write-Host "ExtractInt must be between -512 and 512." -ForegroundColor Red
exit 1
}
}
# Ignore MaxCount if WriteCRC_SE or WriteCRC_BE is set
if ($WriteCRC_SE -ne $null -or $WriteCRC_BE -ne $null) {
$MaxCount = $null
} elseif ($MaxCount -ne $null) {
# Validate the ExtractInt input if provided
try {
$MaxCount = [int]$MaxCount
} catch {
Write-Host "MaxCount (if specified) must be a valid integer." -ForegroundColor Red
exit 0
}
}
# Initialize global variables
$halfChunkSize = $slideSize * 2 # 1024 Two Slides (used for searching)
$chunkSize = $halfChunkSize * 2 # 2048 Total size of the buffer (4 chunks of 512 bytes)
$buffer = $buffer = @() # Global buffer array.
$foundCount = 0
$filePosition = 0
# If needed, prepare the output file
if ($WriteCRC_SE -ne $null -or $WriteCRC_BE -ne $null) {
$outputFile = [System.IO.Path]::Combine(
[System.IO.Path]::GetDirectoryName($BinaryFile),
[System.IO.Path]::GetFileNameWithoutExtension($BinaryFile) + "_modified" + [System.IO.Path]::GetExtension($BinaryFile)
)
if (Test-Path $outputFile) {
# Remove the file
Remove-Item $outputFile -Force
}
$streamWriter = [System.IO.File]::OpenWrite($outputFile)
if ($global:flow_Debug -eq $true) {
Write-Host ("File opened for writing: $outputFile")
}
} else {
$streamWriter = $null
}
function Test-FileLock {
param (
[string]$filePath
)
try {
# Try to open the file with shared read/write access
$fileStream = [System.IO.File]::Open($filePath, 'Open', 'ReadWrite', 'None')
$fileStream.Close()
return $false # File is not locked
}
catch {
return $true # File is locked
}
}
# Function to calculate CRC-16/KERMIT - Renesas calls this CRC-16-CCITT-LSB
function Calculate-CRC16-KERMIT {
param (
[int]$startPosition,
[int]$length
)
$crc = 0x0000 # Initial value for Kermit CRC
$poly = 0x8408 # Reflected polynomial for CRC-16/KERMIT
# Ensure startPosition and length are within buffer bounds
$endPosition = [math]::Min($startPosition + $length, $global:buffer.Length)
for ($i = $startPosition; $i -lt $endPosition; $i++) {
$crc = $crc -bxor $global:buffer[$i]
for ($j = 0; $j -lt 8; $j++) {
if ($crc -band 0x0001) {
$crc = ($crc -shr 1) -bxor $poly
} else {
$crc = $crc -shr 1
}
}
}
return $crc
}
# Function to get the integer value from a byte array at a specific position
function Get-IntFromBytes {
param (
[int]$position
)
# Ensure the position is within the bounds of the buffer
if ($position -lt 0 -or $position -ge $global:buffer.Length - 1) {
Write-Host "Error: Attempt to read integer out of bounds. Position: $position, Buffer Length: $($global:buffer.Length)" -ForegroundColor Red
return "0xNANA 0xNANA"
}
$lowByte = $global:buffer[$position]
$highByte = $global:buffer[$position + 1]
$seInt = "0x{0:X2}{1:X2}" -f $lowByte, $highByte
$beInt = "0x{0:X2}{1:X2}" -f $highByte, $lowByte
return "$seInt $beInt"
}
# Function to write CRC into the buffer
function Write-CRC-ToBuffer {
param (
[int]$position,
[int]$crc,
[string]$endianness
)
# Ensure the position is within the bounds of the global buffer
if ($position -lt 0 -or $position -ge $global:buffer.Length - 1) {
Write-Host "Error: Attempt to write CRC out of bounds. Position: $position, Buffer Length: $($global:buffer.Length)" -ForegroundColor Red
Exit 1
}
if ($endianness -eq "SE") { # Small Endian
$global:buffer[$position] = $crc -band 0xFF
$global:buffer[$position + 1] = ($crc -shr 8) -band 0xFF
} elseif ($endianness -eq "BE") { # Big Endian
$global:buffer[$position] = ($crc -shr 8) -band 0xFF
$global:buffer[$position + 1] = $crc -band 0xFF
}
return
}
function Process-FoundData {
param (
[int]$bufferPosition
)
$exactFilePosition = $Global:filePosition + $bufferPosition
$output = "0x" + [System.Convert]::ToString($exactFilePosition, 16).PadLeft(8, '0')
if ($CalcCRC -ne $null) {
$crcDataStart = $bufferPosition + $Offset
$crc = Calculate-CRC16-KERMIT -startPosition $crcDataStart -length $CalcCRC
$seCRC = "0x{0:X4}" -f $crc
$beCRC = "0x{0:X4}" -f (($crc -shr 8) -bor (($crc -shl 8) -band 0xFF00))
$output += " $seCRC $beCRC"
# Write CRC to buffer if needed
if ($WriteCRC_SE -ne $null) {
Write-CRC-ToBuffer -position ($bufferPosition + $Offset + $WriteCRC_SE) -crc $crc -endianness "SE"
} elseif ($WriteCRC_BE -ne $null) {
Write-CRC-ToBuffer -position ($bufferPosition + $Offset + $WriteCRC_BE) -crc $crc -endianness "BE"
}
}
if ($ExtractInt -ne $null) {
$extractPosition = $bufferPosition + $Offset + $ExtractInt
$intValue = Get-IntFromBytes -position $extractPosition
$output += " $intValue"
}
if (-not ($global:SuppressOutput_Debug -eq $true)) {
Write-Host $output
}
$global:foundCount++
}
function Search-Buffer {
param (
[byte[]]$searchBytes,
[int]$startBufferPosition,
[int]$filePosition
)
$searchLength = $searchBytes.Length
$searchSize = [math]::Min( $global:buffer.Length, $halfChunkSize)
for ($i = $startBufferPosition; $i -le ($searchSize - $searchLength); $i++) {
$matched = $true
for ($j = 0; $j -lt $searchLength; $j++) {
if ($global:buffer[$i + $j] -ne $searchBytes[$j]) {
$matched = $false
break
}
}
if ($matched) {
$foundFilePosition = $filePosition + $i
$nextBufferPosition = $i + $searchLength
return @{
BufferPosition = $i
FilePosition = $foundFilePosition
NextBufferPosition = $nextBufferPosition
}
}
}
return $null
}
function Print-BufferASCII {
param (
[int]$start,
[int]$end
)
# Ensure start and end are within buffer bounds
if ($start -lt 0) { $start = 0 }
if ($end -ge $global:buffer.Length) { $end = $global:buffer.Length - 1 }
# Convert buffer segment to ASCII for debugging
$asciiBuffer = -join ($global:buffer[$start..$end] | ForEach-Object {
if ($_ -ge 32 -and $_ -le 126) {
[char]$_ # Printable ASCII range
} else {
'.' # Non-printable characters
}
})
Write-Host "Buffer printable ASCII contents [$start..$end]: $asciiBuffer"
}
function Save-BufferToFile-Trim {
param (
[bool]$Flush = $false
)
if ($global:buffer.Length -le $slideSize ) {
$Flush = $true
}
# Determine the range of the buffer to save
if ($Flush) {
# Somehow a few extra bytes are at the end of the buffer.
# They cam always be discarded.
# TODO: Figure out where and why, and clean it up!!
if ($false) {
$originalSize = (Get-Item $BinaryFile).Length - 1
$tempSize = (Get-Item $outputFile).Length - 1
$notYetSavedBytes = $originalSize - $tempSize - $global:halfChunkSize -1
Write-Host "originalSize = $originalSize"
Write-Host "tempSize = $tempSize"
Write-Host "notYetSavedBytes = $($notYetSavedBytes+1)"
#Schrink buffer
$global:buffer = $global:buffer[0..$notYetSavedBytes]
}
#Schrink buffer by 5, it seems to work.
$global:buffer = $global:buffer[0..$($global:buffer.Length - 5)]
}
$start = 0
$end = [math]::Min($slideSize, $global:buffer.Length) # Adjust size if buffer is smaller
$bytesToTrim = $end - $start
if ($bytesToTrim -eq 0) {
Return 0
}
if ($streamWriter -ne $null) {
# Write the selected portion of the buffer to the output file
$streamWriter.Write($global:buffer[$start..$end], 0, $bytesToTrim)
if ($global:flow_Debug -eq $true) {
Write-Host "Saved buffer portion [$start..$($end-1)] ([$($start+$Global:filePosition)..$($end+$Global:filePosition-1)]) to the output file."
}
}
# Trim buffer
$global:buffer = $global:buffer[$bytesToTrim..($global:buffer.Length)]
$Global:filePosition += $bytesToTrim
if ($global:flow_Debug -eq $true) {
Write-Host "Buffer now start at file position $($Global:filePosition)"
}
$length = [math]::Max( 0, $global:buffer.Length)
Return $length
}
# Always tries to keep the Global buffer as full as possible.
function Read-IntoBuffer {
param (
[System.IO.FileStream]$stream
)
$missingBytes = $chunksize-$global:buffer.Length
$newBytes = [byte[]]::new($missingBytes)
$bytesRead = $stream.Read($newBytes, 0, $missingBytes)
$global:buffer += $newBytes[0..$bytesRead]
if ($global:flow_Debug -eq $true) {
Write-Host "Appended $bytesRead bytes from file to buffer"
}
if ($global:flow_Debug -eq $true) {
# Print the entire buffer's ASCII contents (adjust start and end as needed)
Print-BufferASCII -start 0 -end ($global:buffer.Length)
}
return $bytesRead
}
# Read-search-modify-write cycle (Represented by R-S-M-W below)
#
# Buffer must be seen as four 512 bytes chunks initially.
#
# First loop:
# 11111222223333344444 (Chunk number)
# RRRRRRRRRRRRRRRRRRRR Fill the entire buffer
# SSSSSSSSSS Search halft of the buffer.
# MMMMMMMMMMMMMMMMMMMM Modify 16bit integer. Worst case is with -Offset = 511 and -WriteCRC = 511, which modified chunk 3 and 4.
# WWWWW Commits the first chunk to file
#
# Middle loops:
# 11111222223333344444 (Chunk number)
# RRRRR Previous chunk 2, 3 and 4 are moved to become chunk 1, 2 and 3. New data is loaded into chunk 4.
# SSSSSSSSSS Search halft of the buffer.
# MMMMMMMMMMMMMMMMMMMM Modify 16bit integer. Worst case is with -Offset = 511 and -WriteCRC = 511, which modified chunk 3 and 4.
# WWWWW Commits the first chunk to file
#
# Final loop:
# 11111222223333344444 (Chunk number)
# RRR Previous chunk 2, 3 and 4 are moved to become chunk 1, 2 and 3. New data is loaded into chunk 4, but may not fill the whole chunk.
# SSSSSSSSSSSSSSSSSS Search the rest of the buffer.
# MMMMMMMMMMMMMMMMMM Modify 16bit integer. Worst case is with -Offset = 511 and -WriteCRC = 511, which modified chunk 3 and 4. Warn if modify is attempted out of bounds.
# WWWWWWWWWWWWWWWWWW Commits all remaining data to file
# Open the file and start processing
if (Test-FileLock -filePath $BinaryFile) {
Write-Host "Error: $BinaryFile is locked." -ForegroundColor Red
Exit 1
} else {
$stream = [System.IO.File]::OpenRead($BinaryFile)
}
try {
if ($Verbose) {
Write-Host "Input file $BinaryFile"
}
$Global:filePosition = 0
$global:foundCount = 0
$startBufferPosition = 0
while ($true) {
if ($global:flow_Debug -eq $true) {
Write-Host "==================================================================================================="
}
$readCount = Read-IntoBuffer -stream $stream
while ($true) {
$searchResult = Search-Buffer -searchBytes $searchBytes -startBufferPosition $startBufferPosition -filePosition $Global:filePosition
if ($null -eq $searchResult) {
# Nothing to be found.
break
}
$bufferPosition = $searchResult.BufferPosition
$startBufferPosition = $searchResult.NextBufferPosition
#Write-Host ""
#Write-Host "Global:filePosition = $Global:filePosition"
#Write-Host "bufferPosition = $bufferPosition"
#Write-Host "searchResult.NextBufferPosition = $($searchResult.NextBufferPosition)"
Process-FoundData -bufferPosition $bufferPosition
}
# Save the processed part of the buffer to file
$rc = Save-BufferToFile-Trim
if ( $rc -eq 0 ) {
break
}
if ($MaxCount -ne $null) {
if ($global:foundCount -eq $MaxCount) {
if ($Verbose) {
Write-Host "Stopping as MaxCount of $MaxCount has been reached."
}
Break
}
}
Continue
if ($global:foundCount -eq 3) {
Write-Host "Debug stopping"
Exit 0
}
if ($global:filePosition -gt 3000) {
Write-Host "Debug stopping"
Exit 0
}
}
if ($Verbose) {
Write-Host "Finished reading and processing file."
}
} finally {
$stream.Close()
if ($streamWriter -ne $null) {
$streamWriter.Close()
}
if ($Verbose) {
Write-Host "Total occurrences found: $global:foundCount"
}
}
# If a file has been written, verify the contents.
if ($WriteCRC_SE -ne $null -or $WriteCRC_BE -ne $null) {
# Check if the original file and the temp file are the same size
$originalSize = (Get-Item $BinaryFile).Length
$tempSize = (Get-Item $outputFile).Length
#Write-Host "originalSize = $originalSize"
#Write-Host "tempSize = $tempSize"
if ($originalSize -ne $tempSize) {
Write-Host "Error: Verify failed - The size of the original file and the modified file do not match." -ForegroundColor Red
exit 1
} elseif ($Verbose) {
Write-Host "Verify: Ok - Newly written file has same size as original."
}
}
# Only execute this block if -ReplaceOriginal and at least one of the -WriteCRC options are specified
if ($WriteCRC_SE -ne $null -or $WriteCRC_BE -ne $null) {
if ($ReplaceOriginal) {
# Extract file name and extension from the original file path
$fileName = [System.IO.Path]::GetFileName($BinaryFile)
$fileDirectory = [System.IO.Path]::GetDirectoryName($BinaryFile)
$originalFileBackup = [System.IO.Path]::Combine([System.IO.Path]::GetFileNameWithoutExtension($BinaryFile) + "_original" + [System.IO.Path]::GetExtension($BinaryFile))
$originalFileBackupFullPath = [System.IO.Path]::Combine($fileDirectory, $originalFileBackup)
# Remove the existing backup file if it exists
if (Test-Path $originalFileBackupFullPath) {
if ($Verbose) {
Write-Host "Removing old backup file."
}
Remove-Item $originalFileBackupFullPath
}
# Rename the original file
Rename-Item -Path $BinaryFile -NewName $originalFileBackup
if ($Verbose) {
Write-Host "Original fil has been backed up to $originalFileBackup"
}
# Rename the modified file to the original file name
Rename-Item -Path $outputFile -NewName $fileName
if ($Verbose) {
Write-Host "Modified file has replaced original file : $BinaryFile"
}
} else{
if ($Verbose) {
Write-Host "Modified file can be found here: $outputFile"
}
}
}
if ($Verbose) {
Write-Host "Done."
} else {
if (-not ($global:SuppressOutput_Debug -eq $true)) {
Write-Output $global:foundCount
}
}
exit 0
0.1 2024-08-20 Initial version.
0.2 2024-08-20 Added Gist URL. Fixed overwriting of backup file (by deleting the old backup)
0.3 2024-08.21 Verbose string was accidently printed in non-verbose mode.
0.4 2024-08.21 Stops nicely with an error message if the input file is locked.
0.4 2024-08.23 Major rewrite to ensure all bytes are processed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment