You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
161 lines
3.8 KiB
Go
161 lines
3.8 KiB
Go
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 MparPaxInsertCommand 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"`
|
|
InsertFilename string `long:"insertfile" short:"i" required:"true" description:"Source File for Insert-Action"`
|
|
}
|
|
|
|
func (command *MparPaxInsertCommand) Execute(args []string) error {
|
|
inputFile, err := os.Open(command.InputFilename)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer inputFile.Close()
|
|
insertFile, err := os.Open(command.InsertFilename)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer insertFile.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-insert.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
|
|
}
|
|
log.Info().Str("fileName", header.Name).Int64("fileSize", header.Size).Msg("copying base-file")
|
|
tarWriter.WriteHeader(header)
|
|
content, err := io.ReadAll(tarReader)
|
|
if err != nil {
|
|
log.Error().Err(err)
|
|
}
|
|
tarWriter.Write(content)
|
|
}
|
|
{
|
|
// insert
|
|
insertFileStat, err := insertFile.Stat()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
insertHeader := &tar.Header{
|
|
Typeflag: tar.TypeReg,
|
|
Size: insertFileStat.Size(),
|
|
ModTime: insertFileStat.ModTime(),
|
|
Name: insertFileStat.Name(),
|
|
Format: tar.FormatGNU,
|
|
}
|
|
tarWriter.WriteHeader(insertHeader)
|
|
content, err := io.ReadAll(insertFile)
|
|
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
|
|
}
|