-
Notifications
You must be signed in to change notification settings - Fork 0
/
deb_reader.go
83 lines (76 loc) · 1.79 KB
/
deb_reader.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package deb
import (
"archive/tar"
"errors"
"fmt"
"io"
"io/ioutil"
"path/filepath"
"strings"
"github.com/myml/ar"
)
// ErrNoSupportVersion 不支持的debian包版本,目前只支持2.0
var (
ErrNoSupportVersion = errors.New("Not support version")
ErrUnknownExtension = errors.New("Unknown extension name")
)
// Reader Deb包读取,类似tar的API
type Reader struct {
arReader *ar.Reader
tarDir string
tarReader *tar.Reader
body io.Reader
}
// NewReader 解析读取deb包,类似tar的操作
func NewReader(r io.Reader) *Reader {
return &Reader{arReader: ar.NewReader(r)}
}
// Next 类似 tar.Reader.Next
func (deb *Reader) Next() (*tar.Header, error) {
if deb.tarReader != nil {
header, err := deb.tarReader.Next()
if err == nil {
deb.body = deb.tarReader
header.Name = filepath.Join(deb.tarDir, header.Name)
return header, nil
}
if err != nil && err != io.EOF {
return nil, fmt.Errorf("read tar %w", err)
}
deb.tarReader = nil
}
header, err := deb.arReader.Next()
if err == io.EOF {
return nil, err
}
if err != nil {
return nil, fmt.Errorf("ar read %w", err)
}
header.Name = filepath.Base(header.Name)
switch strings.SplitN(header.Name, ".", 2)[0] {
case "debian-binary":
b, err := ioutil.ReadAll(deb.arReader)
if err != nil {
return nil, fmt.Errorf("read debian binary %w", err)
}
if string(b) != "2.0\n" {
return nil, fmt.Errorf("unknown version %v", string(b))
}
return deb.Next()
case "control":
deb.tarDir = "DEBIAN"
case "data":
deb.tarDir = ""
default:
return deb.Next()
}
tr, err := decompression(header.Name, deb.arReader)
if err != nil {
return nil, fmt.Errorf("decompression control %w", err)
}
deb.tarReader = tr
return deb.Next()
}
func (deb *Reader) Read(b []byte) (int, error) {
return deb.body.Read(b)
}