Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/myml/ar

go 1.14
Empty file added go.sum
Empty file.
9 changes: 7 additions & 2 deletions reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ THE SOFTWARE.
package ar

import (
"bytes"
"io"
"io/ioutil"
"os"
Expand Down Expand Up @@ -84,8 +85,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
}
Expand Down
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 <blakesmith0@gmail.com>

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 <blakesmith0@gmail.com>

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)
}
}