/*
* JEF - Copyright 2009-2010 Jiyi (mr.jiyi@gmail.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jef.tools.zip;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class TarInputStream extends FilterInputStream {
public TarInputStream(InputStream is) {
this(is, 10240, 512);
}
public TarInputStream(InputStream is, int blockSize) {
this(is, blockSize, 512);
}
public TarInputStream(InputStream is, int blockSize, int recordSize) {
super(is);
buffer = new TarBuffer(is, blockSize, recordSize);
readBuf = null;
oneBuf = new byte[1];
debug = false;
hasHitEOF = false;
v7Format = false;
}
public void setDebug(boolean debug) {
this.debug = debug;
buffer.setDebug(debug);
}
public void close() throws IOException {
buffer.close();
}
public int getRecordSize() {
return buffer.getRecordSize();
}
public int available() throws IOException {
return entrySize - entryOffset;
}
public long skip(long numToSkip) throws IOException {
byte skipBuf[] = new byte[8192];
long skip;
int numRead;
for (skip = numToSkip; skip > 0L; skip -= numRead) {
int realSkip = (int) (skip <= (long) skipBuf.length ? skip : skipBuf.length);
numRead = read(skipBuf, 0, realSkip);
if (numRead == -1)
break;
}
return numToSkip - skip;
}
public boolean markSupported() {
return false;
}
public void mark(int i) {}
public void reset() {}
public TarEntry getNextEntry() throws IOException {
if (hasHitEOF)
return null;
if (currEntry != null) {
int numToSkip = entrySize - entryOffset;
if (debug)
System.err.println("TarInputStream: SKIP currENTRY '" + currEntry.getName() + "' SZ " + entrySize + " OFF " + entryOffset + " skipping " + numToSkip + " bytes");
if (numToSkip > 0)
skip(numToSkip);
readBuf = null;
}
byte headerBuf[] = buffer.readRecord();
if (headerBuf == null) {
if (debug)
System.err.println("READ NULL RECORD");
hasHitEOF = true;
} else if (buffer.isEOFRecord(headerBuf)) {
if (debug)
System.err.println("READ EOF RECORD");
hasHitEOF = true;
}
if (hasHitEOF) {
currEntry = null;
} else {
currEntry = new TarEntry(headerBuf);
if (headerBuf[257] != 117 || headerBuf[258] != 115 || headerBuf[259] != 116 || headerBuf[260] != 97 || headerBuf[261] != 114)
v7Format = true;
if (debug)
System.err.println("TarInputStream: SET CURRENTRY '" + currEntry.getName() + "' size = " + currEntry.getSize());
entryOffset = 0;
entrySize = (int) currEntry.getSize();
}
if (currEntry != null && currEntry.isGNULongNameEntry()) {
StringBuffer longName = new StringBuffer();
byte buf[] = new byte[256];
for (int length = 0; (length = read(buf)) >= 0;)
longName.append(new String(buf, 0, length,TarEntry.DEFAULT_NAME_ENCODING));
getNextEntry();
if (longName.length() > 0 && longName.charAt(longName.length() - 1) == 0)
longName.deleteCharAt(longName.length() - 1);
currEntry.setName(longName.toString());
}
return currEntry;
}
public int read() throws IOException {
int num = read(oneBuf, 0, 1);
return num != -1 ? oneBuf[0] & 255 : -1;
}
public int read(byte buf[], int offset, int numToRead) throws IOException {
int totalRead = 0;
if (entryOffset >= entrySize)
return -1;
if (numToRead + entryOffset > entrySize)
numToRead = entrySize - entryOffset;
if (readBuf != null) {
int sz = numToRead <= readBuf.length ? numToRead : readBuf.length;
System.arraycopy(readBuf, 0, buf, offset, sz);
if (sz >= readBuf.length) {
readBuf = null;
} else {
int newLen = readBuf.length - sz;
byte newBuf[] = new byte[newLen];
System.arraycopy(readBuf, sz, newBuf, 0, newLen);
readBuf = newBuf;
}
totalRead += sz;
numToRead -= sz;
offset += sz;
}
while (numToRead > 0) {
byte rec[] = buffer.readRecord();
if (rec == null)
throw new IOException("unexpected EOF with " + numToRead + " bytes unread");
int sz = numToRead;
int recLen = rec.length;
if (recLen > sz) {
System.arraycopy(rec, 0, buf, offset, sz);
readBuf = new byte[recLen - sz];
System.arraycopy(rec, sz, readBuf, 0, recLen - sz);
} else {
sz = recLen;
System.arraycopy(rec, 0, buf, offset, recLen);
}
totalRead += sz;
numToRead -= sz;
offset += sz;
}
entryOffset += totalRead;
return totalRead;
}
public void copyEntryContents(OutputStream out) throws IOException {
byte buf[] = new byte[32768];
do {
int numRead = read(buf, 0, buf.length);
if (numRead != -1)
out.write(buf, 0, numRead);
else
return;
} while (true);
}
protected boolean debug;
protected boolean hasHitEOF;
protected int entrySize;
protected int entryOffset;
protected byte readBuf[];
protected TarBuffer buffer;
protected TarEntry currEntry;
protected boolean v7Format;
protected byte oneBuf[];
}