Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(13)

Side by Side Diff: src/pkg/archive/tar/writer.go

Issue 162062: code review 162062: Robustness fixes for tar/archive. (Closed)
Patch Set: code review 162062: Robustness fixes for tar/archive. Created 15 years, 3 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/pkg/archive/tar/reader_test.go ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 The Go Authors. All rights reserved. 1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 package tar 5 package tar
6 6
7 // TODO(dsymonds): 7 // TODO(dsymonds):
8 // - catch more errors (no first header, write after close, etc.) 8 // - catch more errors (no first header, write after close, etc.)
9 9
10 import ( 10 import (
11 "io"; 11 "io";
12 "os"; 12 "os";
13 "strconv"; 13 "strconv";
14 "strings"; 14 "strings";
15 ) 15 )
16 16
17 var ( 17 var (
18 » ErrWriteTooLong»= os.NewError("write too long"); 18 » ErrWriteTooLong»» = os.NewError("write too long");
19 » ErrFieldTooLong»= os.NewError("header field too long"); 19 » ErrFieldTooLong»» = os.NewError("header field too long");
20 » ErrWriteAfterClose» = os.NewError("write after close");
20 ) 21 )
21 22
22 // A Writer provides sequential writing of a tar archive in POSIX.1 format. 23 // A Writer provides sequential writing of a tar archive in POSIX.1 format.
23 // A tar archive consists of a sequence of files. 24 // A tar archive consists of a sequence of files.
24 // Call WriteHeader to begin a new file, and then call Write to supply that file 's data, 25 // Call WriteHeader to begin a new file, and then call Write to supply that file 's data,
25 // writing at most hdr.Size bytes in total. 26 // writing at most hdr.Size bytes in total.
26 // 27 //
27 // Example: 28 // Example:
28 // tw := tar.NewWriter(w); 29 // tw := tar.NewWriter(w);
29 // hdr := new(Header); 30 // hdr := new(Header);
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 tw.usedBinary = true; 102 tw.usedBinary = true;
102 for i := len(b) - 1; x > 0 && i >= 0; i-- { 103 for i := len(b) - 1; x > 0 && i >= 0; i-- {
103 b[i] = byte(x); 104 b[i] = byte(x);
104 x >>= 8; 105 x >>= 8;
105 } 106 }
106 b[0] |= 0x80; // highest bit indicates binary format 107 b[0] |= 0x80; // highest bit indicates binary format
107 } 108 }
108 109
109 // WriteHeader writes hdr and prepares to accept the file's contents. 110 // WriteHeader writes hdr and prepares to accept the file's contents.
110 // WriteHeader calls Flush if it is not the first header. 111 // WriteHeader calls Flush if it is not the first header.
112 // Calling after a Close will return ErrWriteAfterClose.
111 func (tw *Writer) WriteHeader(hdr *Header) os.Error { 113 func (tw *Writer) WriteHeader(hdr *Header) os.Error {
114 if tw.closed {
115 return ErrWriteAfterClose
116 }
112 if tw.err == nil { 117 if tw.err == nil {
113 tw.Flush() 118 tw.Flush()
114 } 119 }
115 if tw.err != nil { 120 if tw.err != nil {
116 return tw.err 121 return tw.err
117 } 122 }
118 123
119 tw.nb = int64(hdr.Size); 124 tw.nb = int64(hdr.Size);
120 tw.pad = -tw.nb & (blockSize - 1); // blockSize is a power of two 125 tw.pad = -tw.nb & (blockSize - 1); // blockSize is a power of two
121 126
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 162
158 _, tw.err = tw.w.Write(header); 163 _, tw.err = tw.w.Write(header);
159 164
160 return tw.err; 165 return tw.err;
161 } 166 }
162 167
163 // Write writes to the current entry in the tar archive. 168 // Write writes to the current entry in the tar archive.
164 // Write returns the error ErrWriteTooLong if more than 169 // Write returns the error ErrWriteTooLong if more than
165 // hdr.Size bytes are written after WriteHeader. 170 // hdr.Size bytes are written after WriteHeader.
166 func (tw *Writer) Write(b []byte) (n int, err os.Error) { 171 func (tw *Writer) Write(b []byte) (n int, err os.Error) {
172 if tw.closed {
173 err = ErrWriteTooLong;
174 return;
175 }
167 overwrite := false; 176 overwrite := false;
168 if int64(len(b)) > tw.nb { 177 if int64(len(b)) > tw.nb {
169 b = b[0:tw.nb]; 178 b = b[0:tw.nb];
170 overwrite = true; 179 overwrite = true;
171 } 180 }
172 n, err = tw.w.Write(b); 181 n, err = tw.w.Write(b);
173 tw.nb -= int64(n); 182 tw.nb -= int64(n);
174 if err == nil && overwrite { 183 if err == nil && overwrite {
175 » » err = ErrWriteTooLong 184 » » err = ErrWriteTooLong;
185 » » return;
176 } 186 }
177 tw.err = err; 187 tw.err = err;
178 return; 188 return;
179 } 189 }
180 190
191 // Close closes the tar archive, flushing any unwritten
192 // data to the underlying writer.
181 func (tw *Writer) Close() os.Error { 193 func (tw *Writer) Close() os.Error {
182 if tw.err != nil || tw.closed { 194 if tw.err != nil || tw.closed {
183 return tw.err 195 return tw.err
184 } 196 }
185 tw.Flush(); 197 tw.Flush();
186 tw.closed = true; 198 tw.closed = true;
187 199
188 // trailer: two zero blocks 200 // trailer: two zero blocks
189 for i := 0; i < 2; i++ { 201 for i := 0; i < 2; i++ {
190 _, tw.err = tw.w.Write(zeroBlock); 202 _, tw.err = tw.w.Write(zeroBlock);
191 if tw.err != nil { 203 if tw.err != nil {
192 break 204 break
193 } 205 }
194 } 206 }
195 return tw.err; 207 return tw.err;
196 } 208 }
OLDNEW
« no previous file with comments | « src/pkg/archive/tar/reader_test.go ('k') | no next file » | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b