pax-replace/extract/list
This commit is contained in:
parent
e71cd8a105
commit
01af8d2a7a
5 changed files with 361 additions and 7 deletions
|
@ -3,16 +3,30 @@ package commands
|
||||||
type BaseCommand struct {
|
type BaseCommand struct {
|
||||||
Help HelpCommand `command:"help" description:"Print this help message"`
|
Help HelpCommand `command:"help" description:"Print this help message"`
|
||||||
|
|
||||||
//PrepareBin PrepareBinCommand `command:"prepare" alias:"p" description:"Prepare a Binary file and attach the propietary header to it"`
|
|
||||||
DecryptDBF DecryptDBFCommand `command:"decrypt-dbf" description:"decrypt dbf-data"`
|
DecryptDBF DecryptDBFCommand `command:"decrypt-dbf" description:"decrypt dbf-data"`
|
||||||
DecryptDES DecryptDESCommand `command:"decrypt-des" description:"decrypt des-data"`
|
DecryptDES DecryptDESCommand `command:"decrypt-des" description:"decrypt des-data"`
|
||||||
|
|
||||||
MparUnpack MparUnpackCommand `command:"mpar-unpack" description:"extracts the raw bin from an mpar file"`
|
//CodePlugModify
|
||||||
MparPack MparPackCommand `command:"mpar-pack" description:"creates an mpar file from the binary file and header info"`
|
//CodePlugUnify
|
||||||
|
//CodePlugToJSON
|
||||||
|
//CodePlugFromJSON
|
||||||
|
|
||||||
S19Tree S19TreeCommand `command:"s19-tree" description:"dump s19 tree"`
|
//CodePlugFlash
|
||||||
S19IsolatePart S19IsolatePartitionCommand `command:"s19-isolate-part" description:"isolate a segment from an s19"`
|
//CodePlugDump
|
||||||
S19FromMpar S19FromMparCommand `command:"s19-from-mpar" description:"creates an s19 from an mpar"`
|
|
||||||
|
//KernelModifyFile
|
||||||
|
//KernelRepack
|
||||||
|
|
||||||
|
MparUnpack MparUnpackCommand `command:"mpar-unpack" description:"Extracts the Raw Binary Data from an Partition-File"`
|
||||||
|
MparPack MparPackCommand `command:"mpar-pack" description:"Creates a new Partition-File from Raw Binary-Data"`
|
||||||
|
|
||||||
|
S19Tree S19TreeCommand `command:"s19-tree" description:"Dump the S19 Record Tree and seperate Memory Regions"`
|
||||||
|
S19IsolatePart S19IsolatePartitionCommand `command:"s19-isolate-part" description:"Isolate a Partition from an S19-File"`
|
||||||
|
S19FromMpar S19FromMparCommand `command:"s19-from-mpar" description:"Creates a new S19-File from a Partition-File"`
|
||||||
|
|
||||||
|
MparPaxList MparPaxListCommand `command:"mpar-pax-list" description:"prints the contents of an pax archive within an mpar"`
|
||||||
|
MparPaxExtract MparPaxExtractCommand `command:"mpar-pax-extract" description:"extracts a single file from an pax'd mpar file"`
|
||||||
|
MparPaxReplace MparPaxReplaceCommand `command:"mpar-pax-replace" description:"replaces a single file in a pax'd mpar file"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var MotoCLI BaseCommand
|
var MotoCLI BaseCommand
|
||||||
|
|
|
@ -43,7 +43,7 @@ func (command *MparPackCommand) Execute(args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
originalHeader, err := hex.DecodeString(command.OriginalFullHeader)
|
originalHeader, err := hex.DecodeString(command.OriginalFullHeader)
|
||||||
if len(originalHeader) != 32 {
|
if err != nil {
|
||||||
return errors.New("header invalid")
|
return errors.New("header invalid")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
98
commands/mpar-pax-extract.go
Normal file
98
commands/mpar-pax-extract.go
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"archive/tar"
|
||||||
|
"bytes"
|
||||||
|
"encoding/hex"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.cheetah.cat/cheetah/moto-flash-data/flashpart"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MparPaxExtractCommand struct {
|
||||||
|
InputFilename string `long:"mpar" short:"m" required:"true" description:"input-filename"`
|
||||||
|
TargetFileName string `long:"file" short:"f" required:"true" description:"output-filename"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (command *MparPaxExtractCommand) Execute(args []string) error {
|
||||||
|
inputFile, err := os.Open(command.InputFilename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer inputFile.Close()
|
||||||
|
inputFileStat, err := inputFile.Stat()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info().Int64("fileSize", inputFileStat.Size()).Msg("Reading raw file...")
|
||||||
|
pdata := make([]byte, inputFileStat.Size())
|
||||||
|
_, err = io.ReadFull(inputFile, pdata)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fpHeader := flashpart.ParseFlashPartHeader(pdata[:32])
|
||||||
|
log.Info().Msg(
|
||||||
|
fmt.Sprintf("Media-ID: 0x%02X, Partition Size: 0x%08X / %d bytes, Partition Tag: %s",
|
||||||
|
fpHeader.MediaID,
|
||||||
|
fpHeader.TotalSize,
|
||||||
|
fpHeader.TotalSize,
|
||||||
|
fpHeader.VersionText,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
log.Info().Msg(
|
||||||
|
fmt.Sprintf("Original-Full-Header-Hex: %s", hex.EncodeToString(pdata[:32])),
|
||||||
|
)
|
||||||
|
|
||||||
|
if len(pdata[32:]) != len(pdata)-32 {
|
||||||
|
return errors.New("something doesnt add up")
|
||||||
|
}
|
||||||
|
if len(pdata[32:]) != int(fpHeader.TotalSize)-32 {
|
||||||
|
log.Error().Uint32("header ts", fpHeader.TotalSize).Uint32("len pdata", uint32(len(pdata))).Msg("size mismatch")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
breader := bytes.NewReader(pdata[32:])
|
||||||
|
tarReader := tar.NewReader(breader)
|
||||||
|
|
||||||
|
for {
|
||||||
|
header, err := tarReader.Next()
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if header.Typeflag == tar.TypeReg && !strings.Contains(header.Name, "._") && header.Name == command.TargetFileName {
|
||||||
|
content, err := io.ReadAll(tarReader)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
outputFile, err := os.Create(command.TargetFileName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer outputFile.Close()
|
||||||
|
|
||||||
|
_, err = outputFile.Write(content)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Info().Str("fileName", header.Name).Int64("fileSize", header.Size).Msg("extracted file")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Error().Msg("no file extracted")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
85
commands/mpar-pax-list.go
Normal file
85
commands/mpar-pax-list.go
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"archive/tar"
|
||||||
|
"bytes"
|
||||||
|
"encoding/hex"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"git.cheetah.cat/cheetah/moto-flash-data/flashpart"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MparPaxListCommand struct {
|
||||||
|
SourceFileName string `long:"file" short:"f" required:"true" description:"input-filename"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (command *MparPaxListCommand) Execute(args []string) error {
|
||||||
|
inputFile, err := os.Open(command.SourceFileName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer inputFile.Close()
|
||||||
|
|
||||||
|
inputFileStat, err := inputFile.Stat()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info().Int64("fileSize", inputFileStat.Size()).Msg("Reading raw file...")
|
||||||
|
pdata := make([]byte, inputFileStat.Size())
|
||||||
|
_, err = io.ReadFull(inputFile, pdata)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fpHeader := flashpart.ParseFlashPartHeader(pdata[:32])
|
||||||
|
log.Info().Msg(
|
||||||
|
fmt.Sprintf("Media-ID: 0x%02X, Partition Size: 0x%08X / %d bytes, Partition Tag: %s",
|
||||||
|
fpHeader.MediaID,
|
||||||
|
fpHeader.TotalSize,
|
||||||
|
fpHeader.TotalSize,
|
||||||
|
fpHeader.VersionText,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
log.Info().Msg(
|
||||||
|
fmt.Sprintf("Original-Full-Header-Hex: %s", hex.EncodeToString(pdata[:32])),
|
||||||
|
)
|
||||||
|
|
||||||
|
if len(pdata[32:]) != len(pdata)-32 {
|
||||||
|
return errors.New("something doesnt add up")
|
||||||
|
}
|
||||||
|
if len(pdata[32:]) != int(fpHeader.TotalSize)-32 {
|
||||||
|
log.Error().Uint32("header ts", fpHeader.TotalSize).Uint32("len pdata", uint32(len(pdata))).Msg("size mismatch")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
breader := bytes.NewReader(pdata[32:])
|
||||||
|
tarReader := tar.NewReader(breader)
|
||||||
|
|
||||||
|
for {
|
||||||
|
header, err := tarReader.Next()
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err)
|
||||||
|
}
|
||||||
|
fmt.Println(header)
|
||||||
|
|
||||||
|
// if header.Typeflag == tar.TypeReg && !strings.Contains(header.Name, "._") {
|
||||||
|
// // content, err := io.ReadAll(tarReader)
|
||||||
|
// // if err != nil {
|
||||||
|
// // log.Error().Err(err)
|
||||||
|
// // }
|
||||||
|
|
||||||
|
// fmt.Println("FILE_NAME: ", header.Name)
|
||||||
|
// ///fmt.Println(string(content))
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
157
commands/mpar-pax-replace.go
Normal file
157
commands/mpar-pax-replace.go
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"archive/tar"
|
||||||
|
"bytes"
|
||||||
|
"encoding/hex"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.cheetah.cat/cheetah/moto-flash-data/flashpart"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MparPaxReplaceCommand struct {
|
||||||
|
InputFilename string `long:"mpar" short:"m" required:"true" description:"Source Partition File"`
|
||||||
|
OutputFilename string `long:"output" short:"o" required:"true" description:"Target Partition File"`
|
||||||
|
FindFileName string `long:"file" short:"f" required:"true" description:"Name of the File to Find"`
|
||||||
|
ReplaceWithFilename string `long:"replacewith" short:"r" required:"true" description:"Source Bytes for Replace-Action"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (command *MparPaxReplaceCommand) Execute(args []string) error {
|
||||||
|
inputFile, err := os.Open(command.InputFilename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer inputFile.Close()
|
||||||
|
replaceWithFile, err := os.Open(command.ReplaceWithFilename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer replaceWithFile.Close()
|
||||||
|
|
||||||
|
inputFileStat, err := inputFile.Stat()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info().Int64("fileSize", inputFileStat.Size()).Msg("Reading raw file...")
|
||||||
|
pdata := make([]byte, inputFileStat.Size())
|
||||||
|
_, err = io.ReadFull(inputFile, pdata)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fpHeader := flashpart.ParseFlashPartHeader(pdata[:32])
|
||||||
|
log.Info().Msg(
|
||||||
|
fmt.Sprintf("Media-ID: 0x%02X, Partition Size: 0x%08X / %d bytes, Partition Tag: %s",
|
||||||
|
fpHeader.MediaID,
|
||||||
|
fpHeader.TotalSize,
|
||||||
|
fpHeader.TotalSize,
|
||||||
|
fpHeader.VersionText,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
log.Info().Msg(
|
||||||
|
fmt.Sprintf("Original-Full-Header-Hex: %s", hex.EncodeToString(pdata[:32])),
|
||||||
|
)
|
||||||
|
|
||||||
|
if len(pdata[32:]) != len(pdata)-32 {
|
||||||
|
return errors.New("something doesnt add up")
|
||||||
|
}
|
||||||
|
if len(pdata[32:]) != int(fpHeader.TotalSize)-32 {
|
||||||
|
log.Error().Uint32("header ts", fpHeader.TotalSize).Uint32("len pdata", uint32(len(pdata))).Msg("size mismatch")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
breader := bytes.NewReader(pdata[32:])
|
||||||
|
tarReader := tar.NewReader(breader)
|
||||||
|
|
||||||
|
temporaryPaxFile, _ := os.CreateTemp("", "pax-replace.tar")
|
||||||
|
defer temporaryPaxFile.Close()
|
||||||
|
tarWriter := tar.NewWriter(temporaryPaxFile)
|
||||||
|
defer tarWriter.Close()
|
||||||
|
|
||||||
|
for {
|
||||||
|
header, err := tarReader.Next()
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if header.Typeflag == tar.TypeReg && !strings.Contains(header.Name, "._") && header.Name == command.FindFileName {
|
||||||
|
log.Info().Str("fileName", header.Name).Int64("fileSize", header.Size).Msg("found file to modify")
|
||||||
|
replaceWithFileStat, err := replaceWithFile.Stat()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
header.Size = replaceWithFileStat.Size()
|
||||||
|
header.ModTime = replaceWithFileStat.ModTime()
|
||||||
|
tarWriter.WriteHeader(header)
|
||||||
|
content, err := io.ReadAll(replaceWithFile)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err)
|
||||||
|
}
|
||||||
|
tarWriter.Write(content)
|
||||||
|
} else {
|
||||||
|
tarWriter.WriteHeader(header)
|
||||||
|
content, err := io.ReadAll(tarReader)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err)
|
||||||
|
}
|
||||||
|
tarWriter.Write(content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//log.Error().Msg("no file replaced")
|
||||||
|
|
||||||
|
// create new mpar with same header base
|
||||||
|
_, err = temporaryPaxFile.Seek(0, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
temporaryPaxFileStat, err := temporaryPaxFile.Stat()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
rawData := make([]byte, temporaryPaxFileStat.Size())
|
||||||
|
_, err = io.ReadFull(temporaryPaxFile, rawData)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
outputFile, err := os.Create(command.OutputFilename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer outputFile.Close()
|
||||||
|
|
||||||
|
fpHeader.AdjustRawSize(uint32(len(rawData)))
|
||||||
|
|
||||||
|
log.Info().Msg(
|
||||||
|
fmt.Sprintf("New-Full-Header-Hex: %s", hex.EncodeToString(fpHeader.GetBytes())),
|
||||||
|
)
|
||||||
|
|
||||||
|
fpHeaderNew := flashpart.ParseFlashPartHeader(fpHeader.GetBytes())
|
||||||
|
log.Info().Msg(
|
||||||
|
fmt.Sprintf("Media-ID: 0x%02X, Partition Size: 0x%08X / %d bytes, Partition Tag: %s",
|
||||||
|
fpHeaderNew.MediaID,
|
||||||
|
fpHeaderNew.TotalSize,
|
||||||
|
fpHeaderNew.TotalSize,
|
||||||
|
fpHeaderNew.VersionText,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
_, err = outputFile.Write(fpHeaderNew.GetBytes())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = outputFile.Write(rawData)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue