From 27700a4c90f4bd48249f5012e65ffa2adb555963 Mon Sep 17 00:00:00 2001 From: myml Date: Thu, 9 Jul 2020 18:39:06 +0800 Subject: [PATCH 1/3] fix(Writer): io.ErrShortWrite caused by even byte Issues: https://github.com/blakesmith/ar/issues/4 --- go.mod | 3 +++ go.sum | 0 writer.go | 23 +++++++++++++++++++---- writer_test.go | 40 +++++++++++++++++++++++++++++++++++++++- 4 files changed, 61 insertions(+), 5 deletions(-) create mode 100644 go.mod create mode 100644 go.sum diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..42ea61e --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/myml/ar + +go 1.14 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..e69de29 diff --git a/writer.go b/writer.go index 680f5cb..bd623ac 100644 --- a/writer.go +++ b/writer.go @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 2013 Blake Smith Permission is hereby granted, free of charge, to any person obtaining a copy @@ -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. @@ -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 } @@ -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 @@ -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 +} diff --git a/writer_test.go b/writer_test.go index 36b576a..4a38d41 100644 --- a/writer_test.go +++ b/writer_test.go @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 2013 Blake Smith Permission is hereby granted, free of charge, to any person obtaining a copy @@ -23,8 +23,10 @@ package ar import ( "bytes" + "io" "io/ioutil" "os" + "strings" "testing" "time" ) @@ -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) + } +} From 57214d108c9c3e634830e9af704c3d83123c44af Mon Sep 17 00:00:00 2001 From: myml Date: Tue, 24 Nov 2020 16:57:31 +0800 Subject: [PATCH 2/3] fix: Command Line tools 'ar' mode not use prefix '100' Use `ar -r test.deb test.file` append file, ar header only has 644 instead of 10064 --- reader.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/reader.go b/reader.go index 4b82493..55b8d5c 100644 --- a/reader.go +++ b/reader.go @@ -84,8 +84,12 @@ func (rd *Reader) octal(b []byte) int64 { for i > 0 && b[i] == 32 { i-- } - - n, _ := strconv.ParseInt(string(b[3:i+1]), 8, 64) + start := 3 + // ar command tool mode no hava '100' prefix + if bytes.IndexByte(b, ' ') == 3 { + start = 0 + } + n, _ := strconv.ParseInt(string(b[start:i+1]), 8, 64) return n } From dba7f9c0d41bf4daf431fc0258d4377576c862fd Mon Sep 17 00:00:00 2001 From: myml Date: Tue, 24 Nov 2020 17:06:54 +0800 Subject: [PATCH 3/3] fix: typo --- reader.go | 1 + 1 file changed, 1 insertion(+) diff --git a/reader.go b/reader.go index 55b8d5c..db05f24 100644 --- a/reader.go +++ b/reader.go @@ -22,6 +22,7 @@ THE SOFTWARE. package ar import ( + "bytes" "io" "io/ioutil" "os"