1 18 19 23 24 package org.apache.tools.tar; 25 26 import java.io.FilterOutputStream ; 27 import java.io.OutputStream ; 28 import java.io.IOException ; 29 30 36 public class TarOutputStream extends FilterOutputStream { 37 38 public static final int LONGFILE_ERROR = 0; 39 40 41 public static final int LONGFILE_TRUNCATE = 1; 42 43 44 public static final int LONGFILE_GNU = 2; 45 46 protected boolean debug; 48 protected long currSize; 49 protected String currName; 50 protected long currBytes; 51 protected byte[] oneBuf; 52 protected byte[] recordBuf; 53 protected int assemLen; 54 protected byte[] assemBuf; 55 protected TarBuffer buffer; 56 protected int longFileMode = LONGFILE_ERROR; 57 59 private boolean closed = false; 60 61 65 public TarOutputStream(OutputStream os) { 66 this(os, TarBuffer.DEFAULT_BLKSIZE, TarBuffer.DEFAULT_RCDSIZE); 67 } 68 69 74 public TarOutputStream(OutputStream os, int blockSize) { 75 this(os, blockSize, TarBuffer.DEFAULT_RCDSIZE); 76 } 77 78 84 public TarOutputStream(OutputStream os, int blockSize, int recordSize) { 85 super(os); 86 87 this.buffer = new TarBuffer(os, blockSize, recordSize); 88 this.debug = false; 89 this.assemLen = 0; 90 this.assemBuf = new byte[recordSize]; 91 this.recordBuf = new byte[recordSize]; 92 this.oneBuf = new byte[1]; 93 } 94 95 102 public void setLongFileMode(int longFileMode) { 103 this.longFileMode = longFileMode; 104 } 105 106 107 112 public void setDebug(boolean debugF) { 113 this.debug = debugF; 114 } 115 116 121 public void setBufferDebug(boolean debug) { 122 this.buffer.setDebug(debug); 123 } 124 125 130 public void finish() throws IOException { 131 this.writeEOFRecord(); 134 this.writeEOFRecord(); 135 } 136 137 143 public void close() throws IOException { 144 if (!closed) { 145 this.finish(); 146 this.buffer.close(); 147 out.close(); 148 closed = true; 149 } 150 } 151 152 157 public int getRecordSize() { 158 return this.buffer.getRecordSize(); 159 } 160 161 173 public void putNextEntry(TarEntry entry) throws IOException { 174 if (entry.getName().length() >= TarConstants.NAMELEN) { 175 176 if (longFileMode == LONGFILE_GNU) { 177 TarEntry longLinkEntry = new TarEntry(TarConstants.GNU_LONGLINK, 180 TarConstants.LF_GNUTYPE_LONGNAME); 181 182 longLinkEntry.setSize(entry.getName().length() + 1); 183 putNextEntry(longLinkEntry); 184 write(entry.getName().getBytes()); 185 write(0); 186 closeEntry(); 187 } else if (longFileMode != LONGFILE_TRUNCATE) { 188 throw new RuntimeException ("file name '" + entry.getName() 189 + "' is too long ( > " 190 + TarConstants.NAMELEN + " bytes)"); 191 } 192 } 193 194 entry.writeEntryHeader(this.recordBuf); 195 this.buffer.writeRecord(this.recordBuf); 196 197 this.currBytes = 0; 198 199 if (entry.isDirectory()) { 200 this.currSize = 0; 201 } else { 202 this.currSize = entry.getSize(); 203 } 204 currName = entry.getName(); 205 } 206 207 217 public void closeEntry() throws IOException { 218 if (this.assemLen > 0) { 219 for (int i = this.assemLen; i < this.assemBuf.length; ++i) { 220 this.assemBuf[i] = 0; 221 } 222 223 this.buffer.writeRecord(this.assemBuf); 224 225 this.currBytes += this.assemLen; 226 this.assemLen = 0; 227 } 228 229 if (this.currBytes < this.currSize) { 230 throw new IOException ("entry '" + currName + "' closed at '" 231 + this.currBytes 232 + "' before the '" + this.currSize 233 + "' bytes specified in the header were written"); 234 } 235 } 236 237 245 public void write(int b) throws IOException { 246 this.oneBuf[0] = (byte) b; 247 248 this.write(this.oneBuf, 0, 1); 249 } 250 251 259 public void write(byte[] wBuf) throws IOException { 260 this.write(wBuf, 0, wBuf.length); 261 } 262 263 277 public void write(byte[] wBuf, int wOffset, int numToWrite) throws IOException { 278 if ((this.currBytes + numToWrite) > this.currSize) { 279 throw new IOException ("request to write '" + numToWrite 280 + "' bytes exceeds size in header of '" 281 + this.currSize + "' bytes for entry '" 282 + currName + "'"); 283 284 } 292 293 if (this.assemLen > 0) { 294 if ((this.assemLen + numToWrite) >= this.recordBuf.length) { 295 int aLen = this.recordBuf.length - this.assemLen; 296 297 System.arraycopy(this.assemBuf, 0, this.recordBuf, 0, 298 this.assemLen); 299 System.arraycopy(wBuf, wOffset, this.recordBuf, 300 this.assemLen, aLen); 301 this.buffer.writeRecord(this.recordBuf); 302 303 this.currBytes += this.recordBuf.length; 304 wOffset += aLen; 305 numToWrite -= aLen; 306 this.assemLen = 0; 307 } else { 308 System.arraycopy(wBuf, wOffset, this.assemBuf, this.assemLen, 309 numToWrite); 310 311 wOffset += numToWrite; 312 this.assemLen += numToWrite; 313 numToWrite -= numToWrite; 314 } 315 } 316 317 while (numToWrite > 0) { 323 if (numToWrite < this.recordBuf.length) { 324 System.arraycopy(wBuf, wOffset, this.assemBuf, this.assemLen, 325 numToWrite); 326 327 this.assemLen += numToWrite; 328 329 break; 330 } 331 332 this.buffer.writeRecord(wBuf, wOffset); 333 334 int num = this.recordBuf.length; 335 336 this.currBytes += num; 337 numToWrite -= num; 338 wOffset += num; 339 } 340 } 341 342 346 private void writeEOFRecord() throws IOException { 347 for (int i = 0; i < this.recordBuf.length; ++i) { 348 this.recordBuf[i] = 0; 349 } 350 351 this.buffer.writeRecord(this.recordBuf); 352 } 353 } 354 355 356 | Popular Tags |