From 6976438bb41e88228fb75a94f22b491308f360d2 Mon Sep 17 00:00:00 2001 From: Felicitas Pojtinger Date: Fri, 19 Nov 2021 01:46:12 +0100 Subject: [PATCH] feat: Add structured CSV output to archive, list and restore commands --- cmd/stbak-archive/main.go | 33 +++++++++++++-------------------- cmd/stbak-list/main.go | 22 +++++++++++++++++----- cmd/stbak-restore/main.go | 10 ++++++++-- pkg/formatting/csv.go | 27 +++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 27 deletions(-) create mode 100644 pkg/formatting/csv.go diff --git a/cmd/stbak-archive/main.go b/cmd/stbak-archive/main.go index df76897..1b7bf21 100644 --- a/cmd/stbak-archive/main.go +++ b/cmd/stbak-archive/main.go @@ -8,29 +8,16 @@ import ( "flag" "io" "io/fs" - "log" "os" "path/filepath" - "strconv" "syscall" "time" "github.com/pojntfx/stfs/pkg/controllers" + "github.com/pojntfx/stfs/pkg/formatting" "golang.org/x/sys/unix" ) -const ( - stfsVersionPAX = "STFS.Version" - stfsVersion = 1 - - stfsActionPAX = "STFS.Action" - stfsActionCreate = "CREATE" - stfsActionUpdate = "UPDATE" - stfsActionDelete = "DELETE" - - stfsReplacesPAX = "STFS.Replaces" -) - func main() { drive := flag.String("drive", "/dev/nst0", "Tape or tar file to write to") recordSize := flag.Int("recordSize", 20, "Amount of 512-bit blocks per record") @@ -90,6 +77,7 @@ func main() { } defer tw.Close() + first := true if err := filepath.Walk(*src, func(path string, info fs.FileInfo, err error) error { if err != nil { return err @@ -124,14 +112,19 @@ func main() { hdr.Devminor = int64(unix.Minor(unixStat.Dev)) hdr.Name = path - hdr.PAXRecords = map[string]string{ - stfsVersionPAX: strconv.Itoa(stfsVersion), - stfsActionPAX: stfsActionUpdate, - stfsReplacesPAX: "", - } hdr.Format = tar.FormatPAX - log.Println(hdr) + if first { + if err := formatting.PrintCSV(formatting.TARHeaderCSV); err != nil { + return err + } + + first = false + } + + if err := formatting.PrintCSV(formatting.GetTARHeaderAsCSV(-1, -1, hdr)); err != nil { + return err + } if err := tw.WriteHeader(hdr); err != nil { return err diff --git a/cmd/stbak-list/main.go b/cmd/stbak-list/main.go index ad30278..8d5f3d2 100644 --- a/cmd/stbak-list/main.go +++ b/cmd/stbak-list/main.go @@ -5,10 +5,10 @@ import ( "bufio" "flag" "io" - "log" "os" "github.com/pojntfx/stfs/pkg/controllers" + "github.com/pojntfx/stfs/pkg/formatting" "github.com/pojntfx/stfs/pkg/readers" ) @@ -73,9 +73,13 @@ func main() { } if record == 0 && block == 0 { - log.Println("Record:", 0, "Block:", 0, "Header:", hdr) - } else { - log.Println("Record:", record, "Block:", block, "Header:", hdr) + if err := formatting.PrintCSV(formatting.TARHeaderCSV); err != nil { + panic(err) + } + } + + if err := formatting.PrintCSV(formatting.GetTARHeaderAsCSV(record, block, hdr)); err != nil { + panic(err) } curr, err := f.Seek(0, io.SeekCurrent) @@ -148,7 +152,15 @@ func main() { dirty = false - log.Println("Record:", record, "Block:", block, "Header:", hdr) + if counter.BytesRead == 0 { + if err := formatting.PrintCSV(formatting.TARHeaderCSV); err != nil { + panic(err) + } + } + + if err := formatting.PrintCSV(formatting.GetTARHeaderAsCSV(record, block, hdr)); err != nil { + panic(err) + } nextBytes := int64(counter.BytesRead) + hdr.Size + controllers.BlockSize - 1 diff --git a/cmd/stbak-restore/main.go b/cmd/stbak-restore/main.go index 226d5ad..c343def 100644 --- a/cmd/stbak-restore/main.go +++ b/cmd/stbak-restore/main.go @@ -5,11 +5,11 @@ import ( "bufio" "flag" "io" - "log" "os" "path/filepath" "github.com/pojntfx/stfs/pkg/controllers" + "github.com/pojntfx/stfs/pkg/formatting" ) func main() { @@ -69,7 +69,13 @@ func main() { panic(err) } - log.Println(hdr) + if err := formatting.PrintCSV(formatting.TARHeaderCSV); err != nil { + panic(err) + } + + if err := formatting.PrintCSV(formatting.GetTARHeaderAsCSV(int64(*record), int64(*block), hdr)); err != nil { + panic(err) + } if !*preview { if *dst == "" { diff --git a/pkg/formatting/csv.go b/pkg/formatting/csv.go new file mode 100644 index 0000000..961cb9e --- /dev/null +++ b/pkg/formatting/csv.go @@ -0,0 +1,27 @@ +package formatting + +import ( + "archive/tar" + "encoding/csv" + "fmt" + "os" + "time" +) + +var ( + TARHeaderCSV = []string{ + "record", "block", "typeflag", "name", "linkname", "size", "mode", "uid", "gid", "uname", "gname", "modtime", "accesstime", "changetime", "devmajor", "devminor", "paxrecords", "format", + } +) + +func PrintCSV(input []string) error { + w := csv.NewWriter(os.Stdout) + + return w.WriteAll([][]string{input}) +} + +func GetTARHeaderAsCSV(record int64, block int64, hdr *tar.Header) []string { + return []string{ + fmt.Sprintf("%v", record), fmt.Sprintf("%v", block), fmt.Sprintf("%v", hdr.Typeflag), hdr.Name, hdr.Linkname, fmt.Sprintf("%v", hdr.Size), fmt.Sprintf("%v", hdr.Mode), fmt.Sprintf("%v", hdr.Uid), fmt.Sprintf("%v", hdr.Gid), fmt.Sprintf("%v", hdr.Uname), fmt.Sprintf("%v", hdr.Gname), hdr.ModTime.Format(time.RFC3339), hdr.AccessTime.Format(time.RFC3339), hdr.ChangeTime.Format(time.RFC3339), fmt.Sprintf("%v", hdr.Devmajor), fmt.Sprintf("%v", hdr.Devminor), fmt.Sprintf("%v", hdr.PAXRecords), fmt.Sprintf("%v", hdr.Format), + } +}