feat: Make seek command universal

This commit is contained in:
Felicitas Pojtinger
2021-11-19 00:10:13 +01:00
parent 38819a06d2
commit 621cc0b055
2 changed files with 20 additions and 129 deletions

View File

@@ -1,77 +0,0 @@
package main
import (
"archive/tar"
"bufio"
"flag"
"log"
"os"
"syscall"
"unsafe"
)
// See https://github.com/benmcclelland/mtio
const (
MTIOCTOP = 0x40086d01 // Do magnetic tape operation
MTSEEK = 22 // Seek to block
blockSize = 512
)
// 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")
recordSize := flag.Int("recordSize", 20, "Amount of 512-bit blocks per record")
record := flag.Int("record", 0, "Record to seek too")
block := flag.Int("block", 0, "Block in record to seek too")
flag.Parse()
f, err := os.OpenFile(*file, os.O_RDONLY, os.ModeCharDevice)
if err != nil {
panic(err)
}
defer f.Close()
if err := seekToRecordOnTape(f, int32(*record)); err != nil {
panic(err)
}
br := bufio.NewReaderSize(f, blockSize**recordSize)
if _, err := br.Read(make([]byte, *block*blockSize)); err != nil {
panic(err)
}
tr := tar.NewReader(br)
hdr, err := tr.Next()
if err != nil {
panic(err)
}
log.Println(hdr)
}
func seekToRecordOnTape(f *os.File, record int32) error {
if _, _, err := syscall.Syscall(
syscall.SYS_IOCTL,
f.Fd(),
MTIOCTOP,
uintptr(unsafe.Pointer(
&Operation{
Op: MTSEEK,
Count: record,
},
)),
); err != 0 {
return err
}
return nil
}

View File

@@ -4,7 +4,6 @@ import (
"archive/tar"
"bufio"
"flag"
"io"
"log"
"os"
"syscall"
@@ -51,60 +50,43 @@ func main() {
if err != nil {
panic(err)
}
// Seek to record & block
if _, err := f.Seek(int64((*recordSize*blockSize**record)+*block*blockSize), 0); err != nil {
panic(err)
}
} else {
f, err = os.OpenFile(*file, os.O_RDONLY, os.ModeCharDevice)
if err != nil {
panic(err)
}
// Seek to record (we can't seek to block on tape)
// TODO: Seek to next header here too; currently this only works for the start of each archive/after a filemark
if err := seekToRecordOnTape(f, int32(*record)); err != nil {
panic(err)
}
}
defer f.Close()
var tr *tar.Reader
if fileDescription.Mode().IsRegular() {
tr = tar.NewReader(f)
} else {
br := bufio.NewReaderSize(f, blockSize**recordSize)
tr = tar.NewReader(br)
}
for {
hdr, err := tr.Next()
if err != nil {
// Seek to record and block
if _, err := f.Seek(int64((*recordSize*blockSize**record)+*block*blockSize), 0); err != nil {
panic(err)
}
log.Println(hdr)
currentRecord := int64(0)
if fileDescription.Mode().IsRegular() {
curr, err := f.Seek(0, io.SeekCurrent)
if err != nil {
panic(err)
}
currentRecord = ((curr + hdr.Size) / blockSize) / int64(*recordSize)
} else {
currentRecord, err = getCurrentRecordFromTape(f)
if err != nil {
panic(err)
}
tr = tar.NewReader(f)
} else {
// Seek to record
if err := seekToRecordOnTape(f, int32(*record)); err != nil {
panic(err)
}
if currentRecord > int64(*record) {
break
// Seek to block
br := bufio.NewReaderSize(f, blockSize**recordSize)
if _, err := br.Read(make([]byte, *block*blockSize)); err != nil {
panic(err)
}
tr = tar.NewReader(br)
}
hdr, err := tr.Next()
if err != nil {
panic(err)
}
log.Println(hdr)
}
func seekToRecordOnTape(f *os.File, record int32) error {
@@ -124,17 +106,3 @@ func seekToRecordOnTape(f *os.File, record int32) error {
return nil
}
func getCurrentRecordFromTape(f *os.File) (int64, error) {
pos := &Position{}
if _, _, err := syscall.Syscall(
syscall.SYS_IOCTL,
f.Fd(),
MTIOCPOS,
uintptr(unsafe.Pointer(pos)),
); err != 0 {
return 0, err
}
return pos.BlkNo, nil
}