Skip to content

Commit

Permalink
fix(Writer): io.ErrShortWrite caused by even byte
Browse files Browse the repository at this point in the history
Issues: #4
  • Loading branch information
myml committed Jul 9, 2020
1 parent 809d437 commit f696070
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 5 deletions.
5 changes: 5 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module github.com/myml/ar

go 1.14

require github.com/google/martian v2.1.0+incompatible // indirect
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
23 changes: 19 additions & 4 deletions writer.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*
/*
Copyright (c) 2013 Blake Smith <[email protected]>
Permission is hereby granted, free of charge, to any person obtaining a copy
Expand Down Expand Up @@ -28,7 +28,7 @@ import (
)

var (
ErrWriteTooLong = errors.New("ar: write too long")
ErrWriteTooLong = errors.New("ar: write too long")
)

// Writer provides sequential writing of an ar archive.
Expand All @@ -45,7 +45,7 @@ var (
// }
// io.Copy(archive, data)
type Writer struct {
w io.Writer
w io.Writer
nb int64 // number of unwritten bytes for the current file entry
}

Expand Down Expand Up @@ -92,7 +92,7 @@ func (aw *Writer) Write(b []byte) (n int, err error) {

if len(b)%2 == 1 { // data size must be aligned to an even byte
n2, _ := aw.w.Write([]byte{'\n'})
return n+n2, err
return n + n2, err
}

return
Expand Down Expand Up @@ -122,3 +122,18 @@ func (aw *Writer) WriteHeader(hdr *Header) error {

return err
}

var _ io.ReaderFrom = &Writer{}

// ReadFrom prevent returns io.ErrShortWrite when using io.Copy. This is to make io.Copy() to work correctly.
func (aw *Writer) ReadFrom(r io.Reader) (written int64, err error) {
written, err = io.Copy(aw.w, r)
if err != nil {
return written, err
}
if written%2 == 1 { // data size must be aligned to an even byte
n2, err := aw.w.Write([]byte{'\n'})
return written + int64(n2), err
}
return written, err
}
40 changes: 39 additions & 1 deletion writer_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*
/*
Copyright (c) 2013 Blake Smith <[email protected]>
Permission is hereby granted, free of charge, to any person obtaining a copy
Expand All @@ -23,8 +23,10 @@ package ar

import (
"bytes"
"io"
"io/ioutil"
"os"
"strings"
"testing"
"time"
)
Expand Down Expand Up @@ -90,3 +92,39 @@ func TestWriteTooLong(t *testing.T) {
t.Errorf("Error should have been: %s", ErrWriteTooLong)
}
}

// Use odd byte check error
func TestShortWrite(t *testing.T) {
body := strings.NewReader("Hello world!\n")

hdr := new(Header)
hdr.Size = body.Size()

var buf bytes.Buffer
writer := NewWriter(&buf)
writer.WriteHeader(hdr)
// Hide io.WriteTo interface and io.ReadFrom interface
_, err := io.Copy(io.MultiWriter(writer), io.MultiReader(body))
if err != io.ErrShortWrite {
t.Errorf("Error should have been: %s", io.ErrShortWrite)
}
}

func TestWriteCopy(t *testing.T) {
body := strings.NewReader("Hello world!\n")

hdr := new(Header)
hdr.Size = body.Size()

var buf bytes.Buffer
writer := NewWriter(&buf)
writer.WriteHeader(hdr)
// Only hide io.WriteTo interface
wn, err := io.Copy(writer, io.MultiReader(body))
if err != nil {
t.Fatal(err)
}
if wn != hdr.Size+1 {
t.Errorf("Expected %d to equal %d", wn, hdr.Size+1)
}
}

0 comments on commit f696070

Please sign in to comment.