mirror of
https://github.com/NotAShelf/hexxy.git
synced 2024-11-22 13:20:49 +00:00
[hexxy] add --reverse option and --plain
This commit is contained in:
parent
f45df01756
commit
6d4d21c621
2 changed files with 195 additions and 7 deletions
117
hexxy.go
117
hexxy.go
|
@ -2,6 +2,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
@ -16,6 +17,10 @@ import (
|
||||||
var opts struct {
|
var opts struct {
|
||||||
NoColor bool `short:"N" long:"no-color" description:"do not print output with color"`
|
NoColor bool `short:"N" long:"no-color" description:"do not print output with color"`
|
||||||
OffsetFormat string `short:"t" long:"radix" default:"x" choice:"d" choice:"o" choice:"x" description:"Print offset in [d|o|x] format"`
|
OffsetFormat string `short:"t" long:"radix" default:"x" choice:"d" choice:"o" choice:"x" description:"Print offset in [d|o|x] format"`
|
||||||
|
Reverse bool `short:"r" long:"reverse" description:"re-assemble hexdump output back into binary"`
|
||||||
|
Plain bool `short:"p" long:"plain" description:"plain output without ascii table and offset row [often used with hexxy -r]"`
|
||||||
|
ForceColor bool `short:"F" long:"force-color" description:"color is automatically disabled if output is a pipe, this option forces color output"`
|
||||||
|
Separator string `short:"s" long:"separator" default:"|" description:"separator character for the ascii character table"`
|
||||||
Verbose bool `short:"v" long:"verbose" description:"print debugging information and verbose output"`
|
Verbose bool `short:"v" long:"verbose" description:"print debugging information and verbose output"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,6 +86,7 @@ func printOffset(offset uint64) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func printSeparator(writer io.Writer, newline bool) {
|
func printSeparator(writer io.Writer, newline bool) {
|
||||||
|
// WHY???
|
||||||
if newline {
|
if newline {
|
||||||
fmt.Fprintln(writer, Separator)
|
fmt.Fprintln(writer, Separator)
|
||||||
} else {
|
} else {
|
||||||
|
@ -158,27 +164,97 @@ func Hexdump(file *os.File, color *Color) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func HexdumpPlain(file *os.File) error {
|
||||||
|
// stdout := bufio.NewWriter(os.Stdout)
|
||||||
|
// stderr := os.Stderr
|
||||||
|
// defer stdout.Flush()
|
||||||
|
|
||||||
|
src, err := io.ReadAll(file)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
dst := make([]byte, hex.EncodedLen(len(src)))
|
||||||
|
hex.Encode(dst, src)
|
||||||
|
fmt.Printf("%s\n", dst)
|
||||||
|
|
||||||
|
// reader := bufio.NewReaderSize(file, 10*1024*1024)
|
||||||
|
|
||||||
|
// for {
|
||||||
|
// b, err := reader.ReadByte()
|
||||||
|
// if errors.Is(err, io.EOF) {
|
||||||
|
// break
|
||||||
|
// }
|
||||||
|
// if err != nil {
|
||||||
|
// fmt.Fprintf(stderr, "Failed to read %v: %v\n", file.Name(), err)
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
// stdout.WriteString(fmt.Sprintf("%02x", string(b)))
|
||||||
|
// }
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func plain2Binary(file *os.File) error {
|
||||||
|
|
||||||
|
return reverse(os.Stdout, os.Stdin)
|
||||||
|
// contents, err := io.ReadAll(file)
|
||||||
|
// if err != nil {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
// fmt.Println(len(contents))
|
||||||
|
// fmt.Printf("Binary byte representation: %08b\n", contents)
|
||||||
|
|
||||||
|
// _, err = hex.Decode(contents, dst)
|
||||||
|
// if err != nil {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
// os.Stdout.Write(dst)
|
||||||
|
|
||||||
|
// dest := make([]byte, hex.EncodedLen(len(contents)))
|
||||||
|
// hex.Decode(dest, contents)
|
||||||
|
|
||||||
|
// fmt.Printf("%s\n", dest)
|
||||||
|
|
||||||
|
// return nil
|
||||||
|
}
|
||||||
|
|
||||||
func getOffsetFormat() error {
|
func getOffsetFormat() error {
|
||||||
var prefix string
|
var prefix string
|
||||||
var suffix string
|
var suffix string
|
||||||
|
var sep string
|
||||||
|
|
||||||
|
// turn off color if output is a pipe
|
||||||
|
// idk if I like this though since I often
|
||||||
|
// use hexxy asdf | head -n 10 but I also want to work on --reverse option
|
||||||
|
|
||||||
|
// stat, _ := os.Stdout.Stat()
|
||||||
|
// if stat.Mode()&os.ModeCharDevice == 0 && !opts.ForceColor {
|
||||||
|
// opts.NoColor = true
|
||||||
|
// }
|
||||||
|
|
||||||
if !opts.NoColor {
|
if !opts.NoColor {
|
||||||
prefix = GREY
|
prefix = GREY
|
||||||
suffix = CLR
|
suffix = CLR
|
||||||
|
sep = "│"
|
||||||
} else {
|
} else {
|
||||||
prefix = ""
|
prefix = ""
|
||||||
suffix = ""
|
suffix = ""
|
||||||
|
sep = "|"
|
||||||
}
|
}
|
||||||
|
|
||||||
Separator = prefix + "│" + suffix
|
if opts.Separator != "" {
|
||||||
|
sep = opts.Separator
|
||||||
|
}
|
||||||
|
|
||||||
|
Separator = prefix + sep + suffix
|
||||||
|
|
||||||
switch opts.OffsetFormat {
|
switch opts.OffsetFormat {
|
||||||
case "d":
|
case "d":
|
||||||
OffsetFormat = prefix + "%08d " + suffix
|
OffsetFormat = prefix + "%08d " + suffix
|
||||||
case "o":
|
case "o":
|
||||||
OffsetFormat = prefix + "%08o " + suffix
|
OffsetFormat = prefix + "%08o " + suffix
|
||||||
case "x":
|
case "x":
|
||||||
OffsetFormat = prefix + "%08x " + suffix
|
OffsetFormat = prefix + "%08x " + suffix
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("Offset format must be [d|o|x]")
|
return fmt.Errorf("Offset format must be [d|o|x]")
|
||||||
}
|
}
|
||||||
|
@ -188,6 +264,10 @@ func getOffsetFormat() error {
|
||||||
func Hexxy(args []string) error {
|
func Hexxy(args []string) error {
|
||||||
color := &Color{}
|
color := &Color{}
|
||||||
|
|
||||||
|
if opts.Reverse {
|
||||||
|
return plain2Binary(os.Stdin)
|
||||||
|
}
|
||||||
|
|
||||||
if opts.NoColor {
|
if opts.NoColor {
|
||||||
color.disable = true
|
color.disable = true
|
||||||
}
|
}
|
||||||
|
@ -197,7 +277,11 @@ func Hexxy(args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(args) < 1 && stdinOpen() {
|
if len(args) < 1 && stdinOpen() {
|
||||||
return Hexdump(os.Stdin, color)
|
if opts.Plain {
|
||||||
|
return HexdumpPlain(os.Stdin)
|
||||||
|
} else {
|
||||||
|
return Hexdump(os.Stdin, color)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, f := range args {
|
for _, f := range args {
|
||||||
|
@ -207,8 +291,14 @@ func Hexxy(args []string) error {
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
if err := Hexdump(file, color); err != nil {
|
if opts.Plain {
|
||||||
return err
|
if err := HexdumpPlain(file); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := Hexdump(file, color); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,6 +318,19 @@ func main() {
|
||||||
Debug = log.Printf
|
Debug = log.Printf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if opts.Reverse {
|
||||||
|
// f, err := os.Open(args[0])
|
||||||
|
// if err != nil {
|
||||||
|
// panic(err)
|
||||||
|
// }
|
||||||
|
// defer f.Close()
|
||||||
|
err = plain2Binary(os.Stdin)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
err = getOffsetFormat()
|
err = getOffsetFormat()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
|
85
reverse.go
Normal file
85
reverse.go
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// func reverse(w io.Writer, path string) error {
|
||||||
|
func reverse(w io.Writer, f *os.File) error {
|
||||||
|
// f, err := os.Open(path)
|
||||||
|
// if err != nil {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
// defer f.Close()
|
||||||
|
s := bufio.NewScanner(f)
|
||||||
|
|
||||||
|
star := false
|
||||||
|
var prev uint64
|
||||||
|
var data []byte
|
||||||
|
var zero [16]byte
|
||||||
|
|
||||||
|
for s.Scan() {
|
||||||
|
line := s.Text()
|
||||||
|
if line == "*" {
|
||||||
|
star = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(line) < len("00000000") {
|
||||||
|
return fmt.Errorf("invalid line %q, missing address prefix", line)
|
||||||
|
}
|
||||||
|
|
||||||
|
part := line[:len("00000000")]
|
||||||
|
line = line[len("00000000"):]
|
||||||
|
|
||||||
|
addr, err := strconv.ParseUint(part, 16, 32)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if star {
|
||||||
|
for i := prev + 16; i < addr; i += 16 {
|
||||||
|
data = append(data, zero[:]...)
|
||||||
|
}
|
||||||
|
star = false
|
||||||
|
}
|
||||||
|
|
||||||
|
prev = addr
|
||||||
|
pos := strings.IndexByte(line, '|')
|
||||||
|
|
||||||
|
if pos != -1 {
|
||||||
|
line = line[:pos]
|
||||||
|
}
|
||||||
|
|
||||||
|
for len(line) > 0 {
|
||||||
|
line = strings.TrimSpace(line)
|
||||||
|
pos := strings.IndexByte(line, ' ')
|
||||||
|
if pos == -1 {
|
||||||
|
pos = len(line)
|
||||||
|
}
|
||||||
|
|
||||||
|
part := line[:pos]
|
||||||
|
line = line[pos:]
|
||||||
|
|
||||||
|
b, err := strconv.ParseUint(part, 16, 8)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
data = append(data, byte(b))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := s.Err(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := w.Write(data); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in a new issue