feat: Add counter-based iterator

This commit is contained in:
Felicitas Pojtinger
2021-11-18 02:41:52 +01:00
parent b759a56a7b
commit a38e7bd710
2 changed files with 55 additions and 57 deletions

View File

@@ -39,17 +39,7 @@ func main() {
}
defer f.Close()
if _, _, err := syscall.Syscall(
syscall.SYS_IOCTL,
f.Fd(),
MTIOCTOP,
uintptr(unsafe.Pointer(
&Operation{
Op: MTSEEK,
Count: int32(*record),
},
)),
); err != 0 {
if err := seekToRecordOnTape(f, int32(*record)); err != nil {
panic(err)
}
@@ -67,3 +57,21 @@ func main() {
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

@@ -7,8 +7,6 @@ import (
"io"
"log"
"os"
"syscall"
"unsafe"
)
// See https://github.com/benmcclelland/mtio
@@ -32,6 +30,24 @@ type Operation struct {
Count int32 // Operation count
}
type Counter struct {
reader io.Reader
bytesRead int
}
func (r *Counter) Read(p []byte) (n int, err error) {
n, err = r.reader.Read(p)
r.bytesRead += n
return n, err
}
func (r *Counter) GetBytesRead() int {
return r.bytesRead
}
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")
@@ -119,54 +135,28 @@ func main() {
}
} else {
br := bufio.NewReaderSize(f, blockSize**recordSize)
counter := &Counter{reader: br}
record := int64(0)
block := int64(0)
currentRecord := 0
o:
for {
for currentBlock := 0; currentBlock < *recordSize; currentBlock++ {
if currentRecord%4096 == 0 {
tell, err := getCurrentRecordFromTape(f)
if err != nil {
panic(err)
}
if tell < int64(currentRecord) {
// EOD
break o
}
}
tr := tar.NewReader(br)
hdr, err := tr.Next()
if err != nil {
continue
}
if hdr.Format == tar.FormatUnknown {
continue
}
log.Println("Record:", currentRecord, "Block:", currentBlock, "Header:", hdr)
// TODO: Seek to (curr + hdr.Size)/blockSize if recordToSeekTo != currentRecord, re-write `br`
tr := tar.NewReader(counter)
hdr, err := tr.Next()
if err != nil {
continue
}
currentRecord++
if hdr.Format == tar.FormatUnknown {
continue
}
log.Println("Record:", record, "Block:", block, "Header:", hdr)
nextBytes := int64(counter.GetBytesRead()) + hdr.Size + blockSize - 1
record = nextBytes / (blockSize * int64(*recordSize))
block = (nextBytes - (record * int64(*recordSize) * blockSize)) / blockSize
}
}
}
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
}