1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
8 // - catch more errors (no first header, etc.)
23 ErrWriteTooLong
= errors
.New("archive/tar: write too long")
24 ErrFieldTooLong
= errors
.New("archive/tar: header field too long")
25 ErrWriteAfterClose
= errors
.New("archive/tar: write after close")
26 errNameTooLong
= errors
.New("archive/tar: name too long")
27 errInvalidHeader
= errors
.New("archive/tar: header field too long or contains invalid values")
30 // A Writer provides sequential writing of a tar archive in POSIX.1 format.
31 // A tar archive consists of a sequence of files.
32 // Call WriteHeader to begin a new file, and then call Write to supply that file's data,
33 // writing at most hdr.Size bytes in total.
37 nb
int64 // number of unwritten bytes for current file entry
38 pad
int64 // amount of padding to write after current file entry
40 usedBinary
bool // whether the binary numeric field extension was used
41 preferPax
bool // use pax header instead of binary numeric header
44 // NewWriter creates a new Writer writing to w.
45 func NewWriter(w io
.Writer
) *Writer
{ return &Writer
{w
: w
} }
47 // Flush finishes writing the current file (optional).
48 func (tw
*Writer
) Flush() error
{
50 tw
.err
= fmt
.Errorf("archive/tar: missed writing %d bytes", tw
.nb
)
55 for n
> 0 && tw
.err
== nil {
61 nw
, tw
.err
= tw
.w
.Write(zeroBlock
[0:nr
])
69 // Write s into b, terminating it with a NUL if there is room.
70 // If the value is too long for the field and allowPax is true add a paxheader record instead
71 func (tw
*Writer
) cString(b
[]byte, s
string, allowPax
bool, paxKeyword
string, paxHeaders
map[string]string) {
72 needsPaxHeader
:= allowPax
&& len(s
) > len(b
) ||
!isASCII(s
)
74 paxHeaders
[paxKeyword
] = s
79 tw
.err
= ErrFieldTooLong
85 if len(ascii
) < len(b
) {
90 // Encode x as an octal ASCII string and write it into b with leading zeros.
91 func (tw
*Writer
) octal(b
[]byte, x
int64) {
92 s
:= strconv
.FormatInt(x
, 8)
93 // leading zeros, but leave room for a NUL.
94 for len(s
)+1 < len(b
) {
97 tw
.cString(b
, s
, false, paxNone
, nil)
100 // Write x into b, either as octal or as binary (GNUtar/star extension).
101 // If the value is too long for the field and writingPax is enabled both for the field and the add a paxheader record instead
102 func (tw
*Writer
) numeric(b
[]byte, x
int64, allowPax
bool, paxKeyword
string, paxHeaders
map[string]string) {
104 s
:= strconv
.FormatInt(x
, 8)
110 // If it is too long for octal, and pax is preferred, use a pax header
111 if allowPax
&& tw
.preferPax
{
113 s
:= strconv
.FormatInt(x
, 10)
114 paxHeaders
[paxKeyword
] = s
118 // Too big: use binary (big-endian).
120 for i
:= len(b
) - 1; x
> 0 && i
>= 0; i
-- {
124 b
[0] |
= 0x80 // highest bit indicates binary format
128 minTime
= time
.Unix(0, 0)
129 // There is room for 11 octal digits (33 bits) of mtime.
130 maxTime
= minTime
.Add((1<<33 - 1) * time
.Second
)
133 // WriteHeader writes hdr and prepares to accept the file's contents.
134 // WriteHeader calls Flush if it is not the first header.
135 // Calling after a Close will return ErrWriteAfterClose.
136 func (tw
*Writer
) WriteHeader(hdr
*Header
) error
{
137 return tw
.writeHeader(hdr
, true)
140 // WriteHeader writes hdr and prepares to accept the file's contents.
141 // WriteHeader calls Flush if it is not the first header.
142 // Calling after a Close will return ErrWriteAfterClose.
143 // As this method is called internally by writePax header to allow it to
144 // suppress writing the pax header.
145 func (tw
*Writer
) writeHeader(hdr
*Header
, allowPax
bool) error
{
147 return ErrWriteAfterClose
156 // a map to hold pax header records, if any are needed
157 paxHeaders
:= make(map[string]string)
159 // TODO(shanemhansen): we might want to use PAX headers for
160 // subsecond time resolution, but for now let's just capture
161 // too long fields or non ascii characters
163 header
:= make([]byte, blockSize
)
166 // keep a reference to the filename to allow to overwrite it later if we detect that we can use ustar longnames instead of pax
167 pathHeaderBytes
:= s
.next(fileNameSize
)
169 tw
.cString(pathHeaderBytes
, hdr
.Name
, true, paxPath
, paxHeaders
)
171 // Handle out of range ModTime carefully.
173 if !hdr
.ModTime
.Before(minTime
) && !hdr
.ModTime
.After(maxTime
) {
174 modTime
= hdr
.ModTime
.Unix()
177 tw
.octal(s
.next(8), hdr
.Mode
) // 100:108
178 tw
.numeric(s
.next(8), int64(hdr
.Uid
), true, paxUid
, paxHeaders
) // 108:116
179 tw
.numeric(s
.next(8), int64(hdr
.Gid
), true, paxGid
, paxHeaders
) // 116:124
180 tw
.numeric(s
.next(12), hdr
.Size
, true, paxSize
, paxHeaders
) // 124:136
181 tw
.numeric(s
.next(12), modTime
, false, paxNone
, nil) // 136:148 --- consider using pax for finer granularity
182 s
.next(8) // chksum (148:156)
183 s
.next(1)[0] = hdr
.Typeflag
// 156:157
185 tw
.cString(s
.next(100), hdr
.Linkname
, true, paxLinkpath
, paxHeaders
)
187 copy(s
.next(8), []byte("ustar\x0000")) // 257:265
188 tw
.cString(s
.next(32), hdr
.Uname
, true, paxUname
, paxHeaders
) // 265:297
189 tw
.cString(s
.next(32), hdr
.Gname
, true, paxGname
, paxHeaders
) // 297:329
190 tw
.numeric(s
.next(8), hdr
.Devmajor
, false, paxNone
, nil) // 329:337
191 tw
.numeric(s
.next(8), hdr
.Devminor
, false, paxNone
, nil) // 337:345
193 // keep a reference to the prefix to allow to overwrite it later if we detect that we can use ustar longnames instead of pax
194 prefixHeaderBytes
:= s
.next(155)
195 tw
.cString(prefixHeaderBytes
, "", false, paxNone
, nil) // 345:500 prefix
197 // Use the GNU magic instead of POSIX magic if we used any GNU extensions.
199 copy(header
[257:265], []byte("ustar \x00"))
202 _
, paxPathUsed
:= paxHeaders
[paxPath
]
203 // try to use a ustar header when only the name is too long
204 if !tw
.preferPax
&& len(paxHeaders
) == 1 && paxPathUsed
{
207 if len(hdr
.Name
) > fileNameSize
&& isASCII(hdr
.Name
) {
209 prefix
, suffix
, err
= tw
.splitUSTARLongName(hdr
.Name
)
211 // ok we can use a ustar long name instead of pax, now correct the fields
213 // remove the path field from the pax header. this will suppress the pax header
214 delete(paxHeaders
, paxPath
)
216 // update the path fields
217 tw
.cString(pathHeaderBytes
, suffix
, false, paxNone
, nil)
218 tw
.cString(prefixHeaderBytes
, prefix
, false, paxNone
, nil)
220 // Use the ustar magic if we used ustar long names.
221 if len(prefix
) > 0 && !tw
.usedBinary
{
222 copy(header
[257:265], []byte("ustar\x00"))
228 // The chksum field is terminated by a NUL and a space.
229 // This is different from the other octal fields.
230 chksum
, _
:= checksum(header
)
231 tw
.octal(header
[148:155], chksum
)
235 // problem with header; probably integer too big for a field.
240 for k
, v
:= range hdr
.Xattrs
{
241 paxHeaders
[paxXattr
+k
] = v
245 if len(paxHeaders
) > 0 {
247 return errInvalidHeader
249 if err
:= tw
.writePAXHeader(hdr
, paxHeaders
); err
!= nil {
253 tw
.nb
= int64(hdr
.Size
)
254 tw
.pad
= (blockSize
- (tw
.nb
% blockSize
)) % blockSize
256 _
, tw
.err
= tw
.w
.Write(header
)
260 // writeUSTARLongName splits a USTAR long name hdr.Name.
261 // name must be < 256 characters. errNameTooLong is returned
262 // if hdr.Name can't be split. The splitting heuristic
263 // is compatible with gnu tar.
264 func (tw
*Writer
) splitUSTARLongName(name
string) (prefix
, suffix
string, err error
) {
266 if length
> fileNamePrefixSize
+1 {
267 length
= fileNamePrefixSize
+ 1
268 } else if name
[length
-1] == '/' {
271 i
:= strings
.LastIndex(name
[:length
], "/")
272 // nlen contains the resulting length in the name field.
273 // plen contains the resulting length in the prefix field.
274 nlen
:= len(name
) - i
- 1
276 if i
<= 0 || nlen
> fileNameSize || nlen
== 0 || plen
> fileNamePrefixSize
{
280 prefix
, suffix
= name
[:i
], name
[i
+1:]
284 // writePaxHeader writes an extended pax header to the
286 func (tw
*Writer
) writePAXHeader(hdr
*Header
, paxHeaders
map[string]string) error
{
287 // Prepare extended header
289 ext
.Typeflag
= TypeXHeader
290 // Setting ModTime is required for reader parsing to
291 // succeed, and seems harmless enough.
292 ext
.ModTime
= hdr
.ModTime
293 // The spec asks that we namespace our pseudo files
294 // with the current pid.
296 dir
, file
:= path
.Split(hdr
.Name
)
297 fullName
:= path
.Join(dir
,
298 fmt
.Sprintf("PaxHeaders.%d", pid
), file
)
300 ascii
:= toASCII(fullName
)
301 if len(ascii
) > 100 {
305 // Construct the body
308 for k
, v
:= range paxHeaders
{
309 fmt
.Fprint(&buf
, paxHeader(k
+"="+v
))
312 ext
.Size
= int64(len(buf
.Bytes()))
313 if err
:= tw
.writeHeader(ext
, false); err
!= nil {
316 if _
, err
:= tw
.Write(buf
.Bytes()); err
!= nil {
319 if err
:= tw
.Flush(); err
!= nil {
325 // paxHeader formats a single pax record, prefixing it with the appropriate length
326 func paxHeader(msg
string) string {
327 const padding
= 2 // Extra padding for space and newline
328 size
:= len(msg
) + padding
329 size
+= len(strconv
.Itoa(size
))
330 record
:= fmt
.Sprintf("%d %s\n", size
, msg
)
331 if len(record
) != size
{
332 // Final adjustment if adding size increased
333 // the number of digits in size
335 record
= fmt
.Sprintf("%d %s\n", size
, msg
)
340 // Write writes to the current entry in the tar archive.
341 // Write returns the error ErrWriteTooLong if more than
342 // hdr.Size bytes are written after WriteHeader.
343 func (tw
*Writer
) Write(b
[]byte) (n
int, err error
) {
345 err
= ErrWriteTooLong
349 if int64(len(b
)) > tw
.nb
{
353 n
, err
= tw
.w
.Write(b
)
355 if err
== nil && overwrite
{
356 err
= ErrWriteTooLong
363 // Close closes the tar archive, flushing any unwritten
364 // data to the underlying writer.
365 func (tw
*Writer
) Close() error
{
366 if tw
.err
!= nil || tw
.closed {
375 // trailer: two zero blocks
376 for i
:= 0; i
< 2; i
++ {
377 _
, tw
.err
= tw
.w
.Write(zeroBlock
)