feat: Add counter-based iterator
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user