From 3cfb784b4e863da8034f4b9bd58c8ec50487ebfb Mon Sep 17 00:00:00 2001 From: Felicitas Pojtinger Date: Sun, 14 Nov 2021 19:57:59 +0100 Subject: [PATCH] feat: Add basic write support --- cmd/stfs-eod/main.go | 4 +- cmd/stfs-metadata/main.go | 5 + .../main.go | 0 cmd/stfs-tvf/main.go | 5 + cmd/stfs-uvf/main.go | 120 ++++++++++++++++++ 5 files changed, 131 insertions(+), 3 deletions(-) rename cmd/{stfs-seek-disk => stfs-seek-tape}/main.go (100%) create mode 100644 cmd/stfs-uvf/main.go diff --git a/cmd/stfs-eod/main.go b/cmd/stfs-eod/main.go index f593689..cc69e6e 100644 --- a/cmd/stfs-eod/main.go +++ b/cmd/stfs-eod/main.go @@ -22,7 +22,6 @@ type Operation struct { func main() { file := flag.String("file", "/dev/nst0", "File of tape drive to open") - record := flag.Int("record", 0, "Record to seek too") flag.Parse() @@ -38,8 +37,7 @@ func main() { MTIOCTOP, uintptr(unsafe.Pointer( &Operation{ - Op: MTEOM, - Count: int32(*record), + Op: MTEOM, }, )), ) diff --git a/cmd/stfs-metadata/main.go b/cmd/stfs-metadata/main.go index dccd386..0042ebc 100644 --- a/cmd/stfs-metadata/main.go +++ b/cmd/stfs-metadata/main.go @@ -97,6 +97,11 @@ func main() { break } + // Missing trailer (expected for concatenated tars) + if err == io.ErrUnexpectedEOF { + break + } + panic(err) } diff --git a/cmd/stfs-seek-disk/main.go b/cmd/stfs-seek-tape/main.go similarity index 100% rename from cmd/stfs-seek-disk/main.go rename to cmd/stfs-seek-tape/main.go diff --git a/cmd/stfs-tvf/main.go b/cmd/stfs-tvf/main.go index a3cef1d..fb9071a 100644 --- a/cmd/stfs-tvf/main.go +++ b/cmd/stfs-tvf/main.go @@ -60,6 +60,11 @@ func main() { break } + // Missing trailer (expected for concatenated tars) + if err == io.ErrUnexpectedEOF { + break + } + panic(err) } diff --git a/cmd/stfs-uvf/main.go b/cmd/stfs-uvf/main.go new file mode 100644 index 0000000..659f897 --- /dev/null +++ b/cmd/stfs-uvf/main.go @@ -0,0 +1,120 @@ +package main + +import ( + "archive/tar" + "flag" + "io" + "io/fs" + "log" + "os" + "path/filepath" + "syscall" + "unsafe" +) + +// See https://github.com/benmcclelland/mtio +const ( + MTIOCTOP = 0x40086d01 // Do magnetic tape operation + MTEOM = 12 // Goto end of recorded media (for appending files) +) + +// Operation is struct for MTIOCTOP +type Operation struct { + Op int16 // Operation ID + Pad int16 // Padding to match C structures + Count int32 // Operation count +} + +func main() { + file := flag.String("file", "/dev/nst0", "File (tape drive or tar file) to open") + dir := flag.String("dir", ".", "Directory to add to the file") + + flag.Parse() + + isRegular := true + stat, err := os.Stat(*file) + if err == nil { + isRegular = stat.Mode().IsRegular() + } else { + if os.IsNotExist(err) { + isRegular = true + } else { + panic(err) + } + } + + var f *os.File + if isRegular { + f, err = os.OpenFile(*file, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600) + if err != nil { + panic(err) + } + + // No need to go to end manually due to `os.O_APPEND` + } else { + // Go to end of file + syscall.Syscall( + syscall.SYS_IOCTL, + f.Fd(), + MTIOCTOP, + uintptr(unsafe.Pointer( + &Operation{ + Op: MTEOM, + }, + )), + ) + + f, err = os.OpenFile(*file, os.O_APPEND|os.O_WRONLY, os.ModeCharDevice) + if err != nil { + panic(err) + } + } + defer f.Close() + + tw := tar.NewWriter(f) // We are not closing the tar writer to prevent writing the trailer + + if err := filepath.Walk(*dir, func(path string, info fs.FileInfo, err error) error { + if err != nil { + return err + } + + link := "" + if info.Mode()&os.ModeSymlink == os.ModeSymlink { + if link, err = os.Readlink(path); err != nil { + return err + } + } + + hdr, err := tar.FileInfoHeader(info, link) + if err != nil { + return err + } + + hdr.Name = path + + log.Println(hdr) + + if err := tw.WriteHeader(hdr); err != nil { + return err + } + + // Skip writing non-regular files + if !info.Mode().IsRegular() { + return nil + } + + file, err := os.Open(path) + if err != nil { + return err + } + defer file.Close() + + if _, err := io.Copy(tw, file); err != nil { + return err + } + + return nil + }); err != nil { + panic(err) + } +}