167 lines
3.8 KiB
Go
167 lines
3.8 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"kisekinopureya.com.tr/updater/internal/archive"
|
|
"kisekinopureya.com.tr/updater/internal/logger"
|
|
mountfilesystem "kisekinopureya.com.tr/updater/internal/mountFilesystem"
|
|
"kisekinopureya.com.tr/updater/internal/plymouth"
|
|
)
|
|
|
|
type BlockDevice struct {
|
|
Name string `json:"name"`
|
|
Type string `json:"type"`
|
|
PartType string `json:"parttype"`
|
|
Children []BlockDevice `json:"children,omitempty"`
|
|
}
|
|
|
|
type LSBLK struct {
|
|
BlockDevices []BlockDevice `json:"blockdevices"`
|
|
}
|
|
|
|
type partitionScheme struct {
|
|
EfiDevice string
|
|
RootfsDevice string
|
|
DmVerityDevice string
|
|
//VarDevice string
|
|
}
|
|
|
|
var efiUUID string = "c12a7328-f81f-11d2-ba4b-00a0c93ec93b"
|
|
var rootfsUUID string = "4f68bce3-e8cd-4db1-96e7-fbcaf984b709"
|
|
var dmverityUUID string = "2c7357ed-ebd2-46d9-aec1-23d437ec2bf5"
|
|
|
|
//var varUUID string = "4d21b016-b534-45c2-a9fb-5c16e091fd2d"
|
|
|
|
func findByPartType(devices []BlockDevice, target string) string {
|
|
for attempt := 1; attempt <= 3; attempt++ {
|
|
for _, dev := range devices {
|
|
if dev.PartType != "" && dev.PartType == target {
|
|
return dev.Name
|
|
}
|
|
if len(dev.Children) > 0 {
|
|
if found := findByPartType(dev.Children, target); found != "" {
|
|
return found
|
|
}
|
|
}
|
|
}
|
|
|
|
if attempt < 3 {
|
|
time.Sleep(10 * time.Second)
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
func populatePartitionScheme() partitionScheme {
|
|
|
|
var generatedScheme partitionScheme = partitionScheme{}
|
|
cmd := exec.Command("lsblk", "-J", "-o", "NAME,TYPE,PARTTYPE")
|
|
blockDeviceTypes, err := cmd.Output()
|
|
|
|
if err != nil {
|
|
log.Panic(err)
|
|
}
|
|
|
|
var lsblk LSBLK
|
|
if err := json.Unmarshal(blockDeviceTypes, &lsblk); err != nil {
|
|
log.Panic(err)
|
|
}
|
|
generatedScheme.EfiDevice = findByPartType(lsblk.BlockDevices, efiUUID)
|
|
generatedScheme.RootfsDevice = findByPartType(lsblk.BlockDevices, rootfsUUID)
|
|
generatedScheme.DmVerityDevice = findByPartType(lsblk.BlockDevices, dmverityUUID)
|
|
|
|
return generatedScheme
|
|
}
|
|
|
|
func patchImage(imageFile string, partition string, name string) {
|
|
cmd := exec.Command("dd", "if="+imageFile, "of="+"/dev/"+partition, "bs=4M")
|
|
plymouth.ShowPlymouthMessage("Patching " + name + " partition")
|
|
if err := cmd.Run(); err != nil {
|
|
log.Panic(err)
|
|
}
|
|
}
|
|
|
|
func CopyFile(source, destPath string) error {
|
|
in, err := os.Open(source)
|
|
if err != nil {
|
|
log.Panic(err)
|
|
}
|
|
defer in.Close()
|
|
|
|
if err := os.MkdirAll(filepath.Dir(destPath), 0755); err != nil {
|
|
log.Panic(err)
|
|
}
|
|
|
|
out, err := os.Create(destPath)
|
|
if err != nil {
|
|
log.Panic(err)
|
|
}
|
|
defer out.Close()
|
|
|
|
if _, err := io.Copy(out, in); err != nil {
|
|
log.Panic(err)
|
|
}
|
|
|
|
if err := out.Sync(); err != nil {
|
|
log.Panic(err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func main() {
|
|
logger.InitializeLogger("/mnt/var/log/patcher")
|
|
|
|
if len(os.Args) != 2 {
|
|
fmt.Printf("Usage: %s <metadata>\n", os.Args[0])
|
|
os.Exit(1)
|
|
}
|
|
|
|
f, err := os.Open(os.Args[1])
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
defer f.Close()
|
|
|
|
var meta archive.Output
|
|
if err := json.NewDecoder(f).Decode(&meta); err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
currentPartitionScheme := populatePartitionScheme()
|
|
|
|
fileCount := len(meta.Files)
|
|
|
|
// before 20 and after 80 will be filled by initramfs
|
|
leftProgress := 60/fileCount + 20
|
|
|
|
for _, f := range meta.Files {
|
|
plymouth.ShowPlymouthProgress(leftProgress)
|
|
leftProgress += leftProgress
|
|
|
|
imageFile := f.Name
|
|
imageType := f.Type
|
|
|
|
switch imageType {
|
|
case "rootfs":
|
|
patchImage(imageFile, currentPartitionScheme.RootfsDevice, imageType)
|
|
case "dm-verity":
|
|
patchImage(imageFile, currentPartitionScheme.DmVerityDevice, imageType)
|
|
case "kernel":
|
|
mountPath := "/updates-tmp/efi"
|
|
kernelDir := "/EFI/Linux"
|
|
mountfilesystem.MountFileSystem("/dev/"+currentPartitionScheme.EfiDevice, mountPath, "vfat", 0, "")
|
|
CopyFile(imageFile, mountPath+kernelDir+"/kernel.efi")
|
|
mountfilesystem.UnmountFileSystem(mountPath)
|
|
default:
|
|
}
|
|
}
|
|
}
|