feat: Add structured CSV output to archive, list and restore commands
This commit is contained in:
+13
-20
@@ -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
|
||||
|
||||
+17
-5
@@ -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
|
||||
|
||||
|
||||
@@ -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 == "" {
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user