...
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
150 func blockPadding(offset int64) (n int64) {
151 return -offset & (blockSize - 1)
152 }
153
154 var zeroBlock block
155
156 type block [blockSize]byte
157
158
159 func (b *block) V7() *headerV7 { return (*headerV7)(b) }
160 func (b *block) GNU() *headerGNU { return (*headerGNU)(b) }
161 func (b *block) STAR() *headerSTAR { return (*headerSTAR)(b) }
162 func (b *block) USTAR() *headerUSTAR { return (*headerUSTAR)(b) }
163 func (b *block) Sparse() sparseArray { return sparseArray(b[:]) }
164
165
166
167
168 func (b *block) GetFormat() Format {
169
170 var p parser
171 value := p.parseOctal(b.V7().Chksum())
172 chksum1, chksum2 := b.ComputeChecksum()
173 if p.err != nil || (value != chksum1 && value != chksum2) {
174 return FormatUnknown
175 }
176
177
178 magic := string(b.USTAR().Magic())
179 version := string(b.USTAR().Version())
180 trailer := string(b.STAR().Trailer())
181 switch {
182 case magic == magicUSTAR && trailer == trailerSTAR:
183 return formatSTAR
184 case magic == magicUSTAR:
185 return FormatUSTAR | FormatPAX
186 case magic == magicGNU && version == versionGNU:
187 return FormatGNU
188 default:
189 return formatV7
190 }
191 }
192
193
194
195 func (b *block) SetFormat(format Format) {
196
197 switch {
198 case format.has(formatV7):
199
200 case format.has(FormatGNU):
201 copy(b.GNU().Magic(), magicGNU)
202 copy(b.GNU().Version(), versionGNU)
203 case format.has(formatSTAR):
204 copy(b.STAR().Magic(), magicUSTAR)
205 copy(b.STAR().Version(), versionUSTAR)
206 copy(b.STAR().Trailer(), trailerSTAR)
207 case format.has(FormatUSTAR | FormatPAX):
208 copy(b.USTAR().Magic(), magicUSTAR)
209 copy(b.USTAR().Version(), versionUSTAR)
210 default:
211 panic("invalid format")
212 }
213
214
215
216 var f formatter
217 field := b.V7().Chksum()
218 chksum, _ := b.ComputeChecksum()
219 f.formatOctal(field[:7], chksum)
220 field[7] = ' '
221 }
222
223
224
225
226
227 func (b *block) ComputeChecksum() (unsigned, signed int64) {
228 for i, c := range b {
229 if 148 <= i && i < 156 {
230 c = ' '
231 }
232 unsigned += int64(c)
233 signed += int64(int8(c))
234 }
235 return unsigned, signed
236 }
237
238
239 func (b *block) Reset() {
240 *b = block{}
241 }
242
243 type headerV7 [blockSize]byte
244
245 func (h *headerV7) Name() []byte { return h[000:][:100] }
246 func (h *headerV7) Mode() []byte { return h[100:][:8] }
247 func (h *headerV7) UID() []byte { return h[108:][:8] }
248 func (h *headerV7) GID() []byte { return h[116:][:8] }
249 func (h *headerV7) Size() []byte { return h[124:][:12] }
250 func (h *headerV7) ModTime() []byte { return h[136:][:12] }
251 func (h *headerV7) Chksum() []byte { return h[148:][:8] }
252 func (h *headerV7) TypeFlag() []byte { return h[156:][:1] }
253 func (h *headerV7) LinkName() []byte { return h[157:][:100] }
254
255 type headerGNU [blockSize]byte
256
257 func (h *headerGNU) V7() *headerV7 { return (*headerV7)(h) }
258 func (h *headerGNU) Magic() []byte { return h[257:][:6] }
259 func (h *headerGNU) Version() []byte { return h[263:][:2] }
260 func (h *headerGNU) UserName() []byte { return h[265:][:32] }
261 func (h *headerGNU) GroupName() []byte { return h[297:][:32] }
262 func (h *headerGNU) DevMajor() []byte { return h[329:][:8] }
263 func (h *headerGNU) DevMinor() []byte { return h[337:][:8] }
264 func (h *headerGNU) AccessTime() []byte { return h[345:][:12] }
265 func (h *headerGNU) ChangeTime() []byte { return h[357:][:12] }
266 func (h *headerGNU) Sparse() sparseArray { return sparseArray(h[386:][:24*4+1]) }
267 func (h *headerGNU) RealSize() []byte { return h[483:][:12] }
268
269 type headerSTAR [blockSize]byte
270
271 func (h *headerSTAR) V7() *headerV7 { return (*headerV7)(h) }
272 func (h *headerSTAR) Magic() []byte { return h[257:][:6] }
273 func (h *headerSTAR) Version() []byte { return h[263:][:2] }
274 func (h *headerSTAR) UserName() []byte { return h[265:][:32] }
275 func (h *headerSTAR) GroupName() []byte { return h[297:][:32] }
276 func (h *headerSTAR) DevMajor() []byte { return h[329:][:8] }
277 func (h *headerSTAR) DevMinor() []byte { return h[337:][:8] }
278 func (h *headerSTAR) Prefix() []byte { return h[345:][:131] }
279 func (h *headerSTAR) AccessTime() []byte { return h[476:][:12] }
280 func (h *headerSTAR) ChangeTime() []byte { return h[488:][:12] }
281 func (h *headerSTAR) Trailer() []byte { return h[508:][:4] }
282
283 type headerUSTAR [blockSize]byte
284
285 func (h *headerUSTAR) V7() *headerV7 { return (*headerV7)(h) }
286 func (h *headerUSTAR) Magic() []byte { return h[257:][:6] }
287 func (h *headerUSTAR) Version() []byte { return h[263:][:2] }
288 func (h *headerUSTAR) UserName() []byte { return h[265:][:32] }
289 func (h *headerUSTAR) GroupName() []byte { return h[297:][:32] }
290 func (h *headerUSTAR) DevMajor() []byte { return h[329:][:8] }
291 func (h *headerUSTAR) DevMinor() []byte { return h[337:][:8] }
292 func (h *headerUSTAR) Prefix() []byte { return h[345:][:155] }
293
294 type sparseArray []byte
295
296 func (s sparseArray) Entry(i int) sparseElem { return sparseElem(s[i*24:]) }
297 func (s sparseArray) IsExtended() []byte { return s[24*s.MaxEntries():][:1] }
298 func (s sparseArray) MaxEntries() int { return len(s) / 24 }
299
300 type sparseElem []byte
301
302 func (s sparseElem) Offset() []byte { return s[00:][:12] }
303 func (s sparseElem) Length() []byte { return s[12:][:12] }
304
View as plain text