diff --git a/od/go.mod b/od/go.mod new file mode 100644 index 0000000..c7bb035 --- /dev/null +++ b/od/go.mod @@ -0,0 +1,3 @@ +module git.learnjsthehardway.com/learn-code-the-hard-way/go-coreutils/od + +go 1.24.2 diff --git a/od/main.go b/od/main.go new file mode 100644 index 0000000..b12ac02 --- /dev/null +++ b/od/main.go @@ -0,0 +1,73 @@ +package main + +import ( + "fmt" + "os" + "flag" + "log" + "bufio" +) + +func Fail(err error, format string, v ...any) { + err_format := fmt.Sprintf("ERROR: %v; %s", err, format) + log.Printf(err_format, v...) + os.Exit(1) +} + +type Opts struct { + Width int + Filenames []string + Hex bool + Octal bool + Format string +} + +func parse_opts() (Opts) { + var opts Opts + + flag.IntVar(&opts.Width, "w", 16, "Width of output grid") + flag.BoolVar(&opts.Hex, "x", false, "Output hex bytes") + flag.BoolVar(&opts.Octal, "o", false, "Output octal bytes") + + flag.Parse() + + if flag.NArg() == 0 { + log.Fatal("USAGE: od [files]") + os.Exit(1) + } + + if opts.Hex { + opts.Format = "%0.2x " + } else { + opts.Format = "%0.3o " + } + + opts.Filenames = flag.Args() + return opts +} + +func main() { + opts := parse_opts() + + for _, filename := range opts.Filenames { + reader, err := os.Open(filename) + defer reader.Close() + if err != nil { Fail(err, "can't open: %s", filename) } + + buf := bufio.NewReader(reader) + count := buf.Size() + + fmt.Printf("%0.8o ", 0); + + for index := 0; index < count; index++ { + data, err := buf.ReadByte() + if err != nil { break } + fmt.Printf(opts.Format, data); + + if (index + 1) % opts.Width == 0 { + fmt.Print("\n") + fmt.Printf("%0.8o ", index); + } + } + } +}