1
0
mirror of https://github.com/byReqz/go-etcher.git synced 2025-07-03 19:40:49 +00:00

4 Commits

Author SHA1 Message Date
d0f0957932 make linter happy 2022-12-29 23:01:03 +01:00
17bb76627f add lint workflow 2022-12-29 19:24:23 +01:00
427c4fd990 fmt 2022-03-26 11:12:58 +01:00
947660b773 add output verification 2022-02-08 12:28:49 +01:00
3 changed files with 75 additions and 40 deletions

7
.github/workflows/lint.yml vendored Normal file
View File

@ -0,0 +1,7 @@
name: ci
on: [push]
jobs:
test:
uses: byReqz/workflows/.github/workflows/golint_with_codeql.yml@main

View File

@ -12,6 +12,7 @@ arguments:
-d, --device string target device -d, --device string target device
-f, --force override safety features -f, --force override safety features
-i, --input string input file -i, --input string input file
-n, --no-hash disable hash verification
``` ```
If no image or device is specified, etcher will enter interactive mode and prompt for the missing parameters. If no image or device is specified, etcher will enter interactive mode and prompt for the missing parameters.

107
main.go
View File

@ -1,28 +1,32 @@
package main package main
import ( import (
"crypto/sha256"
"fmt" "fmt"
"os" ac "github.com/JoaoDanielRufino/go-input-autocomplete"
"github.com/briandowns/spinner"
"github.com/fatih/color"
"github.com/schollz/progressbar/v3"
flag "github.com/spf13/pflag"
"io" "io"
"time"
"log" "log"
"strings" "os"
"runtime" "runtime"
"strconv" "strconv"
"github.com/schollz/progressbar/v3" "strings"
"github.com/fatih/color" "time"
"github.com/briandowns/spinner"
flag "github.com/spf13/pflag"
ac "github.com/JoaoDanielRufino/go-input-autocomplete"
) )
var device string var device string
var input string var input string
var force bool var force bool
var disable_hash bool
func init() { func init() {
flag.StringVarP(&device, "device", "d", "", "target device") flag.StringVarP(&device, "device", "d", "", "target device")
flag.StringVarP(&input, "input", "i", "", "input file") flag.StringVarP(&input, "input", "i", "", "input file")
flag.BoolVarP(&force, "force", "f", false, "override safety features") flag.BoolVarP(&force, "force", "f", false, "override safety features")
flag.BoolVarP(&disable_hash, "no-hash", "n", false, "disable hash verification")
flag.Parse() flag.Parse()
} }
@ -88,26 +92,6 @@ func WriteImage(image *os.File, target *os.File, size int64) (int64, error) {
return written, err return written, err
} }
func Sync(image *os.File, target *os.File) error {
err := image.Sync()
if err != nil {
return err
}
err = target.Sync()
if err != nil {
return err
}
err = image.Close()
if err != nil {
return err
}
err = target.Close()
if err != nil {
return err
}
return nil
}
func PrintAvail() { func PrintAvail() {
if runtime.GOOS == "linux" { if runtime.GOOS == "linux" {
block, _ := os.ReadDir("/sys/block") block, _ := os.ReadDir("/sys/block")
@ -136,7 +120,7 @@ func PrintAvail() {
size = size * 512 size = size * 512
size = size / 1024 / 1024 / 1024 size = size / 1024 / 1024 / 1024
fmt.Print(" * ", "/dev/" + target) fmt.Print(" * ", "/dev/"+target)
if size > 0 { if size > 0 {
fmt.Print(" [", size, "GB]\n") fmt.Print(" [", size, "GB]\n")
} else { } else {
@ -163,7 +147,7 @@ func main() {
} else if len(flag.Args()) > 0 { } else if len(flag.Args()) > 0 {
if input == flag.Args()[0] && len(flag.Args()) > 1 { if input == flag.Args()[0] && len(flag.Args()) > 1 {
device = flag.Args()[1] device = flag.Args()[1]
} else if input != flag.Args()[0] && len(flag.Args()) > 0 { } else if input != flag.Args()[0] && len(flag.Args()) > 0 {
device = flag.Args()[0] device = flag.Args()[0]
} }
} }
@ -196,7 +180,7 @@ func main() {
inputsize = statinput.Size() inputsize = statinput.Size()
inputisblock = false inputisblock = false
} else { } else {
inputsize, err = image.Seek(0, io.SeekEnd) inputsize, _ = image.Seek(0, io.SeekEnd)
inputisblock = true inputisblock = true
_, _ = image.Seek(0, 0) _, _ = image.Seek(0, 0)
} }
@ -216,6 +200,17 @@ func main() {
targetisblock = true targetisblock = true
_, _ = target.Seek(0, 0) _, _ = target.Seek(0, 0)
} }
prehash := sha256.New()
if !(force || disable_hash) {
if err != nil {
s.Stop()
fmt.Println("\r[", color.RedString("✘"), "] Getting file details ")
log.Fatal(err)
}
_, err = io.Copy(prehash, image)
_, _ = image.Seek(0, 0)
}
if err != nil { if err != nil {
s.Stop() s.Stop()
fmt.Println("\r[", color.RedString("✘"), "] Getting file details ") fmt.Println("\r[", color.RedString("✘"), "] Getting file details ")
@ -224,23 +219,23 @@ func main() {
s.Stop() s.Stop()
fmt.Println("\r[", color.GreenString("✓"), "] Getting file details ") fmt.Println("\r[", color.GreenString("✓"), "] Getting file details ")
} }
inputmb := fmt.Sprint("[", inputsize / 1024 / 1024, "MB]") inputmb := fmt.Sprint("[", inputsize/1024/1024, "MB]")
devicemb := fmt.Sprint("[", targetsize / 1024 / 1024, "MB]") devicemb := fmt.Sprint("[", targetsize/1024/1024, "MB]")
var inputblock string var inputblock string
var targetblock string var targetblock string
if inputisblock == true { if inputisblock {
inputblock = "[Blockdevice]" inputblock = "[Blockdevice]"
} else { } else {
inputblock = "[File]" inputblock = "[File]"
} }
if targetisblock == true { if targetisblock {
targetblock = "[Blockdevice]" targetblock = "[Blockdevice]"
} else { } else {
targetblock = "[File]" targetblock = "[File]"
} }
fmt.Println("[", color.BlueString("i"), "] Input device/file: " + input, inputmb, inputblock) fmt.Println("[", color.BlueString("i"), "] Input device/file: "+input, inputmb, inputblock)
fmt.Println("[", color.BlueString("i"), "] Output device/file: " + device, devicemb, targetblock) fmt.Println("[", color.BlueString("i"), "] Output device/file: "+device, devicemb, targetblock)
if force == false { if !force {
if inputsize > targetsize { if inputsize > targetsize {
fmt.Println("[", color.RedString("w"), "]", color.RedString(" Warning:"), "Input file seems to be bigger than the destination!") fmt.Println("[", color.RedString("w"), "]", color.RedString(" Warning:"), "Input file seems to be bigger than the destination!")
} }
@ -248,11 +243,12 @@ func main() {
var yesno string var yesno string
_, _ = fmt.Scanln(&yesno) _, _ = fmt.Scanln(&yesno)
yesno = strings.TrimSpace(yesno) yesno = strings.TrimSpace(yesno)
if ! (yesno == "y" || yesno == "Y") { if !(yesno == "y" || yesno == "Y") {
log.Fatal("aborted") log.Fatal("aborted")
} }
} }
written, err := WriteImage(image, target, inputsize) written, err := WriteImage(image, target, inputsize)
_, _ = target.Seek(0, 0)
if err != nil { if err != nil {
fmt.Println("\r[", color.RedString("✘"), "] Writing image,", written, "bytes written ") fmt.Println("\r[", color.RedString("✘"), "] Writing image,", written, "bytes written ")
log.Fatal(err) log.Fatal(err)
@ -263,7 +259,13 @@ func main() {
s.Prefix = "[ " s.Prefix = "[ "
s.Suffix = " ] Syncing" s.Suffix = " ] Syncing"
s.Start() s.Start()
err = Sync(image, target) err = image.Sync()
if err != nil {
s.Stop()
fmt.Println("\r[", color.RedString("✘"), "] Syncing ")
log.Fatal(err)
}
err = target.Sync()
if err != nil { if err != nil {
s.Stop() s.Stop()
fmt.Println("\r[", color.RedString("✘"), "] Syncing ") fmt.Println("\r[", color.RedString("✘"), "] Syncing ")
@ -272,4 +274,29 @@ func main() {
s.Stop() s.Stop()
fmt.Println("\r[", color.GreenString("✓"), "] Syncing ") fmt.Println("\r[", color.GreenString("✓"), "] Syncing ")
} }
if !(force || disable_hash) {
s.Prefix = "[ "
s.Suffix = " ] Verifying"
s.Start()
posthash := sha256.New()
_, err = io.CopyN(posthash, target, inputsize)
presum := fmt.Sprintf("%x", prehash.Sum(nil))
postsum := fmt.Sprintf("%x", posthash.Sum(nil))
if err != nil || presum != postsum {
s.Stop()
fmt.Println("\r[", color.RedString("✘"), "] Verifying ")
log.Fatal(err)
} else {
s.Stop()
fmt.Println("\r[", color.GreenString("✓"), "] Verifying ")
}
}
err = image.Close()
if err != nil {
log.Fatal(err)
}
err = target.Close()
if err != nil {
log.Fatal(err)
}
} }