1
2
3
4
5 package tar
6
7 import "strings"
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 type Format int
47
48
49 const (
50
51 _ Format = (1 << iota) / 4
52
53
54 FormatUnknown
55
56
57 formatV7
58
59
60
61
62
63
64
65
66
67
68 FormatUSTAR
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84 FormatPAX
85
86
87
88
89
90
91
92
93
94
95
96
97
98 FormatGNU
99
100
101
102
103 formatSTAR
104
105 formatMax
106 )
107
108 func (f Format) has(f2 Format) bool { return f&f2 != 0 }
109 func (f *Format) mayBe(f2 Format) { *f |= f2 }
110 func (f *Format) mayOnlyBe(f2 Format) { *f &= f2 }
111 func (f *Format) mustNotBe(f2 Format) { *f &^= f2 }
112
113 var formatNames = map[Format]string{
114 formatV7: "V7", FormatUSTAR: "USTAR", FormatPAX: "PAX", FormatGNU: "GNU", formatSTAR: "STAR",
115 }
116
117 func (f Format) String() string {
118 var ss []string
119 for f2 := Format(1); f2 < formatMax; f2 <<= 1 {
120 if f.has(f2) {
121 ss = append(ss, formatNames[f2])
122 }
123 }
124 switch len(ss) {
125 case 0:
126 return "<unknown>"
127 case 1:
128 return ss[0]
129 default:
130 return "(" + strings.Join(ss, " | ") + ")"
131 }
132 }
133
134
135 const (
136 magicGNU, versionGNU = "ustar ", " \x00"
137 magicUSTAR, versionUSTAR = "ustar\x00", "00"
138 trailerSTAR = "tar\x00"
139 )
140
141
142 const (
143 blockSize = 512
144 nameSize = 100
145 prefixSize = 155
146
147
148
149 maxSpecialFileSize = 1 << 20
150
151
152
153
154
155 maxSparseFileEntries = 1 << 20
156 )
157
158
159
160 func blockPadding(offset int64) (n int64) {
161 return -offset & (blockSize - 1)
162 }
163
164 var zeroBlock block
165
166 type block [blockSize]byte
167
168
169 func (b *block) toV7() *headerV7 { return (*headerV7)(b) }
170 func (b *block) toGNU() *headerGNU { return (*headerGNU)(b) }
171 func (b *block) toSTAR() *headerSTAR { return (*headerSTAR)(b) }
172 func (b *block) toUSTAR() *headerUSTAR { return (*headerUSTAR)(b) }
173 func (b *block) toSparse() sparseArray { return sparseArray(b[:]) }
174
175
176
177
178 func (b *block) getFormat() Format {
179
180 var p parser
181 value := p.parseOctal(b.toV7().chksum())
182 chksum1, chksum2 := b.computeChecksum()
183 if p.err != nil || (value != chksum1 && value != chksum2) {
184 return FormatUnknown
185 }
186
187
188 magic := string(b.toUSTAR().magic())
189 version := string(b.toUSTAR().version())
190 trailer := string(b.toSTAR().trailer())
191 switch {
192 case magic == magicUSTAR && trailer == trailerSTAR:
193 return formatSTAR
194 case magic == magicUSTAR:
195 return FormatUSTAR | FormatPAX
196 case magic == magicGNU && version == versionGNU:
197 return FormatGNU
198 default:
199 return formatV7
200 }
201 }
202
203
204
205 func (b *block) setFormat(format Format) {
206
207 switch {
208 case format.has(formatV7):
209
210 case format.has(FormatGNU):
211 copy(b.toGNU().magic(), magicGNU)
212 copy(b.toGNU().version(), versionGNU)
213 case format.has(formatSTAR):
214 copy(b.toSTAR().magic(), magicUSTAR)
215 copy(b.toSTAR().version(), versionUSTAR)
216 copy(b.toSTAR().trailer(), trailerSTAR)
217 case format.has(FormatUSTAR | FormatPAX):
218 copy(b.toUSTAR().magic(), magicUSTAR)
219 copy(b.toUSTAR().version(), versionUSTAR)
220 default:
221 panic("invalid format")
222 }
223
224
225
226 var f formatter
227 field := b.toV7().chksum()
228 chksum, _ := b.computeChecksum()
229 f.formatOctal(field[:7], chksum)
230 field[7] = ' '
231 }
232
233
234
235
236
237 func (b *block) computeChecksum() (unsigned, signed int64) {
238 for i, c := range b {
239 if 148 <= i && i < 156 {
240 c = ' '
241 }
242 unsigned += int64(c)
243 signed += int64(int8(c))
244 }
245 return unsigned, signed
246 }
247
248
249 func (b *block) reset() {
250 *b = block{}
251 }
252
253 type headerV7 [blockSize]byte
254
255 func (h *headerV7) name() []byte { return h[000:][:100] }
256 func (h *headerV7) mode() []byte { return h[100:][:8] }
257 func (h *headerV7) uid() []byte { return h[108:][:8] }
258 func (h *headerV7) gid() []byte { return h[116:][:8] }
259 func (h *headerV7) size() []byte { return h[124:][:12] }
260 func (h *headerV7) modTime() []byte { return h[136:][:12] }
261 func (h *headerV7) chksum() []byte { return h[148:][:8] }
262 func (h *headerV7) typeFlag() []byte { return h[156:][:1] }
263 func (h *headerV7) linkName() []byte { return h[157:][:100] }
264
265 type headerGNU [blockSize]byte
266
267 func (h *headerGNU) v7() *headerV7 { return (*headerV7)(h) }
268 func (h *headerGNU) magic() []byte { return h[257:][:6] }
269 func (h *headerGNU) version() []byte { return h[263:][:2] }
270 func (h *headerGNU) userName() []byte { return h[265:][:32] }
271 func (h *headerGNU) groupName() []byte { return h[297:][:32] }
272 func (h *headerGNU) devMajor() []byte { return h[329:][:8] }
273 func (h *headerGNU) devMinor() []byte { return h[337:][:8] }
274 func (h *headerGNU) accessTime() []byte { return h[345:][:12] }
275 func (h *headerGNU) changeTime() []byte { return h[357:][:12] }
276 func (h *headerGNU) sparse() sparseArray { return sparseArray(h[386:][:24*4+1]) }
277 func (h *headerGNU) realSize() []byte { return h[483:][:12] }
278
279 type headerSTAR [blockSize]byte
280
281 func (h *headerSTAR) v7() *headerV7 { return (*headerV7)(h) }
282 func (h *headerSTAR) magic() []byte { return h[257:][:6] }
283 func (h *headerSTAR) version() []byte { return h[263:][:2] }
284 func (h *headerSTAR) userName() []byte { return h[265:][:32] }
285 func (h *headerSTAR) groupName() []byte { return h[297:][:32] }
286 func (h *headerSTAR) devMajor() []byte { return h[329:][:8] }
287 func (h *headerSTAR) devMinor() []byte { return h[337:][:8] }
288 func (h *headerSTAR) prefix() []byte { return h[345:][:131] }
289 func (h *headerSTAR) accessTime() []byte { return h[476:][:12] }
290 func (h *headerSTAR) changeTime() []byte { return h[488:][:12] }
291 func (h *headerSTAR) trailer() []byte { return h[508:][:4] }
292
293 type headerUSTAR [blockSize]byte
294
295 func (h *headerUSTAR) v7() *headerV7 { return (*headerV7)(h) }
296 func (h *headerUSTAR) magic() []byte { return h[257:][:6] }
297 func (h *headerUSTAR) version() []byte { return h[263:][:2] }
298 func (h *headerUSTAR) userName() []byte { return h[265:][:32] }
299 func (h *headerUSTAR) groupName() []byte { return h[297:][:32] }
300 func (h *headerUSTAR) devMajor() []byte { return h[329:][:8] }
301 func (h *headerUSTAR) devMinor() []byte { return h[337:][:8] }
302 func (h *headerUSTAR) prefix() []byte { return h[345:][:155] }
303
304 type sparseArray []byte
305
306 func (s sparseArray) entry(i int) sparseElem { return sparseElem(s[i*24:]) }
307 func (s sparseArray) isExtended() []byte { return s[24*s.maxEntries():][:1] }
308 func (s sparseArray) maxEntries() int { return len(s) / 24 }
309
310 type sparseElem []byte
311
312 func (s sparseElem) offset() []byte { return s[00:][:12] }
313 func (s sparseElem) length() []byte { return s[12:][:12] }
314
View as plain text