fix: Ensure that full records are written to tape so that EOF marks work

This commit is contained in:
Felicitas Pojtinger
2021-11-21 19:14:47 +01:00
parent 7681c5517e
commit 5bf40bf7cb
4 changed files with 76 additions and 20 deletions

View File

@@ -10,6 +10,7 @@ import (
"github.com/pojntfx/stfs/pkg/adapters"
"github.com/pojntfx/stfs/pkg/controllers"
"github.com/pojntfx/stfs/pkg/counters"
"github.com/pojntfx/stfs/pkg/formatting"
"github.com/spf13/cobra"
"github.com/spf13/viper"
@@ -83,11 +84,14 @@ var archiveCmd = &cobra.Command{
dirty := false
var tw *tar.Writer
var bw *bufio.Writer
var counter *counters.CounterWriter
if isRegular {
tw = tar.NewWriter(f)
} else {
bw := bufio.NewWriterSize(f, controllers.BlockSize*viper.GetInt(recordSizeFlag))
tw = tar.NewWriter(bw)
bw = bufio.NewWriterSize(f, controllers.BlockSize*viper.GetInt(recordSizeFlag))
counter = &counters.CounterWriter{Writer: bw, BytesRead: 0}
tw = tar.NewWriter(counter)
}
defer func() {
// Only write the trailer if we wrote to the archive
@@ -95,6 +99,19 @@ var archiveCmd = &cobra.Command{
if err := tw.Close(); err != nil {
panic(err)
}
if !isRegular {
if controllers.BlockSize*viper.GetInt(recordSizeFlag)-counter.BytesRead > 0 {
// Fill the rest of the record with zeros
if _, err := bw.Write(make([]byte, controllers.BlockSize*viper.GetInt(recordSizeFlag)-counter.BytesRead)); err != nil {
panic(err)
}
}
if err := bw.Flush(); err != nil {
panic(err)
}
}
}
}()

View File

@@ -2,11 +2,13 @@ package cmd
import (
"archive/tar"
"bufio"
"context"
"os"
"github.com/pojntfx/stfs/pkg/controllers"
"github.com/pojntfx/stfs/pkg/converters"
"github.com/pojntfx/stfs/pkg/counters"
"github.com/pojntfx/stfs/pkg/formatting"
"github.com/pojntfx/stfs/pkg/pax"
"github.com/pojntfx/stfs/pkg/persisters"
@@ -61,13 +63,35 @@ var removeCmd = &cobra.Command{
defer f.Close()
dirty := false
tw := tar.NewWriter(f)
var tw *tar.Writer
var bw *bufio.Writer
var counter *counters.CounterWriter
if isRegular {
tw = tar.NewWriter(f)
} else {
bw = bufio.NewWriterSize(f, controllers.BlockSize*viper.GetInt(recordSizeFlag))
counter = &counters.CounterWriter{Writer: bw, BytesRead: 0}
tw = tar.NewWriter(counter)
}
defer func() {
// Only write the trailer if we wrote to the archive
if dirty {
if err := tw.Close(); err != nil {
panic(err)
}
if !isRegular {
if controllers.BlockSize*viper.GetInt(recordSizeFlag)-counter.BytesRead > 0 {
// Fill the rest of the record with zeros
if _, err := bw.Write(make([]byte, controllers.BlockSize*viper.GetInt(recordSizeFlag)-counter.BytesRead)); err != nil {
panic(err)
}
}
if err := bw.Flush(); err != nil {
panic(err)
}
}
}
}()
@@ -109,6 +133,7 @@ var removeCmd = &cobra.Command{
}
func init() {
removeCmd.PersistentFlags().IntP(recordSizeFlag, "e", 20, "Amount of 512-bit blocks per record")
removeCmd.PersistentFlags().StringP(nameFlag, "n", "", "Name of the file to remove")
viper.AutomaticEnv()

View File

@@ -0,0 +1,31 @@
package counters
import "io"
type CounterReader struct {
Reader io.Reader
BytesRead int
}
func (r *CounterReader) Read(p []byte) (n int, err error) {
n, err = r.Reader.Read(p)
r.BytesRead += n
return n, err
}
type CounterWriter struct {
Writer io.Writer
BytesRead int
}
func (w *CounterWriter) Write(p []byte) (n int, err error) {
n, err = w.Writer.Write(p)
w.BytesRead += n
return n, err
}

View File

@@ -1,17 +0,0 @@
package readers
import "io"
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
}