mirror of
				https://github.com/NotAShelf/hexxy.git
				synced 2025-10-31 19:32:37 +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…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 mizi
				mizi