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
17 changes: 9 additions & 8 deletions common.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 @@ -26,17 +26,18 @@ import (
)

const (
HEADER_BYTE_SIZE = 60
GLOBAL_HEADER = "!<arch>\n"
HEADER_BYTE_SIZE = 60
GLOBAL_HEADER = "!<arch>\n"
GLOBAL_HEADER_LENGTH = 8
)

type Header struct {
Name string
Name string
ModTime time.Time
Uid int
Gid int
Mode int64
Size int64
Uid int
Gid int
Mode int64
Size int64
}

type slicer []byte
Expand Down
46 changes: 35 additions & 11 deletions reader.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 @@ -22,16 +22,22 @@ THE SOFTWARE.
package ar

import (
"bytes"
"errors"
"io"
"io/ioutil"
"os"
"strconv"
"time"
)

var (
ErrBadMagicHeader = errors.New("ar: bad magic header")
)

// Provides read access to an ar archive.
// Call next to skip files
//
//
// Example:
// reader := NewReader(f)
// var buf bytes.Buffer
Expand All @@ -47,8 +53,8 @@ import (
// }

type Reader struct {
r io.Reader
nb int64
r io.Reader
nb int64
pad int64
}

Expand All @@ -59,17 +65,33 @@ func NewReader(r io.Reader) *Reader {
return &Reader{r: r}
}

// NewStrictReader returns a strict ar reader on r. It checks the global ar
// (magic) header.
func NewStrictReader(r io.Reader) (*Reader, error) {
var b bytes.Buffer
if _, err := io.CopyN(&b, r, GLOBAL_HEADER_LENGTH); err != nil {
if errors.Is(err, io.EOF) {
return nil, ErrBadMagicHeader
}
return nil, err
}
if string(b.Bytes()) != GLOBAL_HEADER {
return nil, ErrBadMagicHeader
}
return &Reader{r: r}, nil
}

func (rd *Reader) string(b []byte) string {
i := len(b)-1
i := len(b) - 1
for i > 0 && b[i] == 32 {
i--
}

return string(b[0:i+1])
return string(b[0 : i+1])
}

func (rd *Reader) numeric(b []byte) int64 {
i := len(b)-1
i := len(b) - 1
for i > 0 && b[i] == 32 {
i--
}
Expand All @@ -80,11 +102,13 @@ func (rd *Reader) numeric(b []byte) int64 {
}

func (rd *Reader) octal(b []byte) int64 {
i := len(b)-1
i := len(b) - 1
for i > 0 && b[i] == 32 {
i--
}

if i <= 2 {
return 0
}
n, _ := strconv.ParseInt(string(b[3:i+1]), 8, 64)

return n
Expand Down Expand Up @@ -129,14 +153,14 @@ func (rd *Reader) readHeader() (*Header, error) {
}

// Call Next() to skip to the next file in the archive file.
// Returns a Header which contains the metadata about the
// Returns a Header which contains the metadata about the
// file in the archive.
func (rd *Reader) Next() (*Header, error) {
err := rd.skipUnread()
if err != nil {
return nil, err
}

return rd.readHeader()
}

Expand Down
40 changes: 39 additions & 1 deletion reader_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 Down Expand Up @@ -64,6 +64,44 @@ func TestReadHeader(t *testing.T) {
}
}

func TestReadStrictHeader(t *testing.T) {
f, err := os.Open("./fixtures/hello.a")
defer f.Close()

if err != nil {
t.Errorf(err.Error())
}
reader, err := NewStrictReader(f)
if err != nil {
t.Fatalf(err.Error())
}
header, err := reader.Next()
if err != nil {
t.Errorf(err.Error())
}

expectedName := "hello.txt"
if header.Name != expectedName {
t.Errorf("Header name should be %s but is %s", expectedName, header.Name)
}
expectedModTime := time.Unix(1361157466, 0)
if header.ModTime != expectedModTime {
t.Errorf("ModTime should be %s but is %s", expectedModTime, header.ModTime)
}
expectedUid := 501
if header.Uid != expectedUid {
t.Errorf("Uid should be %d but is %d", expectedUid, header.Uid)
}
expectedGid := 20
if header.Gid != expectedGid {
t.Errorf("Gid should be %d but is %d", expectedGid, header.Gid)
}
expectedMode := int64(0644)
if header.Mode != expectedMode {
t.Errorf("Mode should be %d but is %d", expectedMode, header.Mode)
}
}

func TestReadBody(t *testing.T) {
f, err := os.Open("./fixtures/hello.a")
defer f.Close()
Expand Down