1 18 19 23 24 package org.apache.tools.tar; 25 26 import java.io.FilterInputStream ; 27 import java.io.IOException ; 28 import java.io.InputStream ; 29 import java.io.OutputStream ; 30 31 38 public class TarInputStream extends FilterInputStream { 39 40 protected boolean debug; 42 protected boolean hasHitEOF; 43 protected long entrySize; 44 protected long entryOffset; 45 protected byte[] readBuf; 46 protected TarBuffer buffer; 47 protected TarEntry currEntry; 48 49 54 protected byte[] oneBuf; 55 56 58 62 public TarInputStream(InputStream is) { 63 this(is, TarBuffer.DEFAULT_BLKSIZE, TarBuffer.DEFAULT_RCDSIZE); 64 } 65 66 71 public TarInputStream(InputStream is, int blockSize) { 72 this(is, blockSize, TarBuffer.DEFAULT_RCDSIZE); 73 } 74 75 81 public TarInputStream(InputStream is, int blockSize, int recordSize) { 82 super(is); 83 84 this.buffer = new TarBuffer(is, blockSize, recordSize); 85 this.readBuf = null; 86 this.oneBuf = new byte[1]; 87 this.debug = false; 88 this.hasHitEOF = false; 89 } 90 91 96 public void setDebug(boolean debug) { 97 this.debug = debug; 98 this.buffer.setDebug(debug); 99 } 100 101 105 public void close() throws IOException { 106 this.buffer.close(); 107 } 108 109 114 public int getRecordSize() { 115 return this.buffer.getRecordSize(); 116 } 117 118 130 public int available() throws IOException { 131 if (this.entrySize - this.entryOffset > Integer.MAX_VALUE) { 132 return Integer.MAX_VALUE; 133 } 134 return (int) (this.entrySize - this.entryOffset); 135 } 136 137 147 public long skip(long numToSkip) throws IOException { 148 byte[] skipBuf = new byte[8 * 1024]; 153 long skip = numToSkip; 154 while (skip > 0) { 155 int realSkip = (int) (skip > skipBuf.length ? skipBuf.length : skip); 156 int numRead = this.read(skipBuf, 0, realSkip); 157 if (numRead == -1) { 158 break; 159 } 160 skip -= numRead; 161 } 162 return (numToSkip - skip); 163 } 164 165 170 public boolean markSupported() { 171 return false; 172 } 173 174 179 public void mark(int markLimit) { 180 } 181 182 185 public void reset() { 186 } 187 188 201 public TarEntry getNextEntry() throws IOException { 202 if (this.hasHitEOF) { 203 return null; 204 } 205 206 if (this.currEntry != null) { 207 long numToSkip = this.entrySize - this.entryOffset; 208 209 if (this.debug) { 210 System.err.println("TarInputStream: SKIP currENTRY '" 211 + this.currEntry.getName() + "' SZ " 212 + this.entrySize + " OFF " 213 + this.entryOffset + " skipping " 214 + numToSkip + " bytes"); 215 } 216 217 if (numToSkip > 0) { 218 this.skip(numToSkip); 219 } 220 221 this.readBuf = null; 222 } 223 224 byte[] headerBuf = this.buffer.readRecord(); 225 226 if (headerBuf == null) { 227 if (this.debug) { 228 System.err.println("READ NULL RECORD"); 229 } 230 this.hasHitEOF = true; 231 } else if (this.buffer.isEOFRecord(headerBuf)) { 232 if (this.debug) { 233 System.err.println("READ EOF RECORD"); 234 } 235 this.hasHitEOF = true; 236 } 237 238 if (this.hasHitEOF) { 239 this.currEntry = null; 240 } else { 241 this.currEntry = new TarEntry(headerBuf); 242 243 if (this.debug) { 244 System.err.println("TarInputStream: SET CURRENTRY '" 245 + this.currEntry.getName() 246 + "' size = " 247 + this.currEntry.getSize()); 248 } 249 250 this.entryOffset = 0; 251 252 this.entrySize = this.currEntry.getSize(); 253 } 254 255 if (this.currEntry != null && this.currEntry.isGNULongNameEntry()) { 256 StringBuffer longName = new StringBuffer (); 258 byte[] buf = new byte[256]; 259 int length = 0; 260 while ((length = read(buf)) >= 0) { 261 longName.append(new String (buf, 0, length)); 262 } 263 getNextEntry(); 264 if (this.currEntry == null) { 265 return null; 268 } 269 if (longName.length() > 0 271 && longName.charAt(longName.length() - 1) == 0) { 272 longName.deleteCharAt(longName.length() - 1); 273 } 274 this.currEntry.setName(longName.toString()); 275 } 276 277 return this.currEntry; 278 } 279 280 288 public int read() throws IOException { 289 int num = this.read(this.oneBuf, 0, 1); 290 return num == -1 ? -1 : ((int) this.oneBuf[0]) & 0xFF; 291 } 292 293 306 public int read(byte[] buf, int offset, int numToRead) throws IOException { 307 int totalRead = 0; 308 309 if (this.entryOffset >= this.entrySize) { 310 return -1; 311 } 312 313 if ((numToRead + this.entryOffset) > this.entrySize) { 314 numToRead = (int) (this.entrySize - this.entryOffset); 315 } 316 317 if (this.readBuf != null) { 318 int sz = (numToRead > this.readBuf.length) ? this.readBuf.length 319 : numToRead; 320 321 System.arraycopy(this.readBuf, 0, buf, offset, sz); 322 323 if (sz >= this.readBuf.length) { 324 this.readBuf = null; 325 } else { 326 int newLen = this.readBuf.length - sz; 327 byte[] newBuf = new byte[newLen]; 328 329 System.arraycopy(this.readBuf, sz, newBuf, 0, newLen); 330 331 this.readBuf = newBuf; 332 } 333 334 totalRead += sz; 335 numToRead -= sz; 336 offset += sz; 337 } 338 339 while (numToRead > 0) { 340 byte[] rec = this.buffer.readRecord(); 341 342 if (rec == null) { 343 throw new IOException ("unexpected EOF with " + numToRead 345 + " bytes unread"); 346 } 347 348 int sz = numToRead; 349 int recLen = rec.length; 350 351 if (recLen > sz) { 352 System.arraycopy(rec, 0, buf, offset, sz); 353 354 this.readBuf = new byte[recLen - sz]; 355 356 System.arraycopy(rec, sz, this.readBuf, 0, recLen - sz); 357 } else { 358 sz = recLen; 359 360 System.arraycopy(rec, 0, buf, offset, recLen); 361 } 362 363 totalRead += sz; 364 numToRead -= sz; 365 offset += sz; 366 } 367 368 this.entryOffset += totalRead; 369 370 return totalRead; 371 } 372 373 380 public void copyEntryContents(OutputStream out) throws IOException { 381 byte[] buf = new byte[32 * 1024]; 382 383 while (true) { 384 int numRead = this.read(buf, 0, buf.length); 385 386 if (numRead == -1) { 387 break; 388 } 389 390 out.write(buf, 0, numRead); 391 } 392 } 393 } 394 | Popular Tags |