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.)
19 ErrWriteTooLong
= errors
.New("archive/tar: write too long")
20 ErrFieldTooLong
= errors
.New("archive/tar: header field too long")
21 ErrWriteAfterClose
= errors
.New("archive/tar: write after close")
24 // A Writer provides sequential writing of a tar archive in POSIX.1 format.
25 // A tar archive consists of a sequence of files.
26 // Call WriteHeader to begin a new file, and then call Write to supply that file's data,
27 // writing at most hdr.Size bytes in total.
30 // tw := tar.NewWriter(w)
31 // hdr := new(tar.Header)
32 // hdr.Size = length of data in bytes
33 // // populate other hdr fields as desired
34 // if err := tw.WriteHeader(hdr); err != nil {
42 nb
int64 // number of unwritten bytes for current file entry
43 pad
int64 // amount of padding to write after current file entry
45 usedBinary
bool // whether the binary numeric field extension was used
48 // NewWriter creates a new Writer writing to w.
49 func NewWriter(w io
.Writer
) *Writer
{ return &Writer
{w
: w
} }
51 // Flush finishes writing the current file (optional).
52 func (tw
*Writer
) Flush() error
{
54 tw
.err
= fmt
.Errorf("archive/tar: missed writing %d bytes", tw
.nb
)
59 for n
> 0 && tw
.err
== nil {
65 nw
, tw
.err
= tw
.w
.Write(zeroBlock
[0:nr
])
73 // Write s into b, terminating it with a NUL if there is room.
74 func (tw
*Writer
) cString(b
[]byte, s
string) {
77 tw
.err
= ErrFieldTooLong
87 // Encode x as an octal ASCII string and write it into b with leading zeros.
88 func (tw
*Writer
) octal(b
[]byte, x
int64) {
89 s
:= strconv
.FormatInt(x
, 8)
90 // leading zeros, but leave room for a NUL.
91 for len(s
)+1 < len(b
) {
97 // Write x into b, either as octal or as binary (GNUtar/star extension).
98 func (tw
*Writer
) numeric(b
[]byte, x
int64) {
100 s
:= strconv
.FormatInt(x
, 8)
105 // Too big: use binary (big-endian).
107 for i
:= len(b
) - 1; x
> 0 && i
>= 0; i
-- {
111 b
[0] |
= 0x80 // highest bit indicates binary format
115 minTime
= time
.Unix(0, 0)
116 // There is room for 11 octal digits (33 bits) of mtime.
117 maxTime
= minTime
.Add((1<<33 - 1) * time
.Second
)
120 // WriteHeader writes hdr and prepares to accept the file's contents.
121 // WriteHeader calls Flush if it is not the first header.
122 // Calling after a Close will return ErrWriteAfterClose.
123 func (tw
*Writer
) WriteHeader(hdr
*Header
) error
{
125 return ErrWriteAfterClose
134 tw
.nb
= int64(hdr
.Size
)
135 tw
.pad
= -tw
.nb
& (blockSize
- 1) // blockSize is a power of two
137 header
:= make([]byte, blockSize
)
140 // TODO(dsymonds): handle names longer than 100 chars
141 copy(s
.next(100), []byte(hdr
.Name
))
143 // Handle out of range ModTime carefully.
145 if !hdr
.ModTime
.Before(minTime
) && !hdr
.ModTime
.After(maxTime
) {
146 modTime
= hdr
.ModTime
.Unix()
149 tw
.octal(s
.next(8), hdr
.Mode
) // 100:108
150 tw
.numeric(s
.next(8), int64(hdr
.Uid
)) // 108:116
151 tw
.numeric(s
.next(8), int64(hdr
.Gid
)) // 116:124
152 tw
.numeric(s
.next(12), hdr
.Size
) // 124:136
153 tw
.numeric(s
.next(12), modTime
) // 136:148
154 s
.next(8) // chksum (148:156)
155 s
.next(1)[0] = hdr
.Typeflag
// 156:157
156 tw
.cString(s
.next(100), hdr
.Linkname
) // linkname (157:257)
157 copy(s
.next(8), []byte("ustar\x0000")) // 257:265
158 tw
.cString(s
.next(32), hdr
.Uname
) // 265:297
159 tw
.cString(s
.next(32), hdr
.Gname
) // 297:329
160 tw
.numeric(s
.next(8), hdr
.Devmajor
) // 329:337
161 tw
.numeric(s
.next(8), hdr
.Devminor
) // 337:345
163 // Use the GNU magic instead of POSIX magic if we used any GNU extensions.
165 copy(header
[257:265], []byte("ustar \x00"))
168 // The chksum field is terminated by a NUL and a space.
169 // This is different from the other octal fields.
170 chksum
, _
:= checksum(header
)
171 tw
.octal(header
[148:155], chksum
)
175 // problem with header; probably integer too big for a field.
179 _
, tw
.err
= tw
.w
.Write(header
)
184 // Write writes to the current entry in the tar archive.
185 // Write returns the error ErrWriteTooLong if more than
186 // hdr.Size bytes are written after WriteHeader.
187 func (tw
*Writer
) Write(b
[]byte) (n
int, err error
) {
189 err
= ErrWriteTooLong
193 if int64(len(b
)) > tw
.nb
{
197 n
, err
= tw
.w
.Write(b
)
199 if err
== nil && overwrite
{
200 err
= ErrWriteTooLong
207 // Close closes the tar archive, flushing any unwritten
208 // data to the underlying writer.
209 func (tw
*Writer
) Close() error
{
210 if tw
.err
!= nil || tw
.closed {
219 // trailer: two zero blocks
220 for i
:= 0; i
< 2; i
++ {
221 _
, tw
.err
= tw
.w
.Write(zeroBlock
)