...
1 package asm
2
3 import (
4 "io"
5
6 "github.com/vbatts/tar-split/archive/tar"
7 "github.com/vbatts/tar-split/tar/storage"
8 )
9
10
11
12
13
14
15
16
17
18
19
20 func NewInputTarStream(r io.Reader, p storage.Packer, fp storage.FilePutter) (io.Reader, error) {
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 pR, pW := io.Pipe()
38 outputRdr := io.TeeReader(r, pW)
39
40
41 if fp == nil {
42 fp = storage.NewDiscardFilePutter()
43 }
44
45 go func() {
46 tr := tar.NewReader(outputRdr)
47 tr.RawAccounting = true
48 for {
49 hdr, err := tr.Next()
50 if err != nil {
51 if err != io.EOF {
52 pW.CloseWithError(err)
53 return
54 }
55
56
57 if b := tr.RawBytes(); len(b) > 0 {
58 _, err := p.AddEntry(storage.Entry{
59 Type: storage.SegmentType,
60 Payload: b,
61 })
62 if err != nil {
63 pW.CloseWithError(err)
64 return
65 }
66 }
67 break
68 }
69 if hdr == nil {
70 break
71 }
72
73 if b := tr.RawBytes(); len(b) > 0 {
74 _, err := p.AddEntry(storage.Entry{
75 Type: storage.SegmentType,
76 Payload: b,
77 })
78 if err != nil {
79 pW.CloseWithError(err)
80 return
81 }
82 }
83
84 var csum []byte
85 if hdr.Size > 0 {
86 var err error
87 _, csum, err = fp.Put(hdr.Name, tr)
88 if err != nil {
89 pW.CloseWithError(err)
90 return
91 }
92 }
93
94 entry := storage.Entry{
95 Type: storage.FileType,
96 Size: hdr.Size,
97 Payload: csum,
98 }
99
100 entry.SetName(hdr.Name)
101
102
103 _, err = p.AddEntry(entry)
104 if err != nil {
105 pW.CloseWithError(err)
106 return
107 }
108
109 if b := tr.RawBytes(); len(b) > 0 {
110 _, err = p.AddEntry(storage.Entry{
111 Type: storage.SegmentType,
112 Payload: b,
113 })
114 if err != nil {
115 pW.CloseWithError(err)
116 return
117 }
118 }
119 }
120
121
122
123
124
125
126 const paddingChunkSize = 1024 * 1024
127 var paddingChunk [paddingChunkSize]byte
128 for {
129 var isEOF bool
130 n, err := outputRdr.Read(paddingChunk[:])
131 if err != nil {
132 if err != io.EOF {
133 pW.CloseWithError(err)
134 return
135 }
136 isEOF = true
137 }
138 if n != 0 {
139 _, err = p.AddEntry(storage.Entry{
140 Type: storage.SegmentType,
141 Payload: paddingChunk[:n],
142 })
143 if err != nil {
144 pW.CloseWithError(err)
145 return
146 }
147 }
148 if isEOF {
149 break
150 }
151 }
152 pW.Close()
153 }()
154
155 return pR, nil
156 }
157
View as plain text