Avoid reliance on fs.ErrClosed in SparseWriter users

Neither of the SparseWriter users actually _wants_ the underlying
WriteSeeker to be closed; so, don't.

That makes it clear where the responsibility for closing the file
lies, and allows us to remove the reliance on the destinations
reliably returning ErrClosed.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
This commit is contained in:
Miloslav Trmač
2024-03-07 14:23:29 +01:00
parent 4c6505be5f
commit 5e0b7e54c0
10 changed files with 18 additions and 24 deletions

View File

@ -14,14 +14,18 @@ type WriteSeekCloser interface {
}
type sparseWriter struct {
file WriteSeekCloser
file io.WriteSeeker
// Invariant between method calls:
// The contents of the file match the contents passed to Write, except that pendingZeroes trailing zeroes have not been written.
// Also, the data that _has_ been written does not end with a zero byte (i.e. pendingZeroes is the largest possible value.
pendingZeroes int64
}
func NewSparseWriter(file WriteSeekCloser) *sparseWriter {
// NewSparseWriter returns a WriteCloser for underlying file which creates
// holes where appropriate.
// NOTE: The caller must .Close() both the returned sparseWriter AND the underlying file,
// in that order.
func NewSparseWriter(file io.WriteSeeker) *sparseWriter {
return &sparseWriter{
file: file,
pendingZeroes: 0,
@ -121,18 +125,15 @@ func (sw *sparseWriter) Close() error {
if sw.pendingZeroes != 0 {
if holeSize := sw.pendingZeroes - 1; holeSize >= zerosThreshold {
if err := sw.createHole(holeSize); err != nil {
sw.file.Close()
return err
}
sw.pendingZeroes -= holeSize
}
var zeroArray [zerosThreshold]byte
if _, err := sw.file.Write(zeroArray[:sw.pendingZeroes]); err != nil {
sw.file.Close()
return err
}
}
err := sw.file.Close()
sw.file = nil
return err
return nil
}