aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/tar/TarInputStream.java
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/tar/TarInputStream.java')
-rw-r--r--framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/tar/TarInputStream.java660
1 files changed, 0 insertions, 660 deletions
diff --git a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/tar/TarInputStream.java b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/tar/TarInputStream.java
deleted file mode 100644
index 57827a2c..00000000
--- a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/tar/TarInputStream.java
+++ /dev/null
@@ -1,660 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- *
- */
-
-/*
- * This package is based on the work done by Timothy Gerard Endres
- * (time@ice.com) to whom the Ant project is very grateful for his great code.
- */
-
-package org.apache.tools.tar;
-
-import java.io.ByteArrayOutputStream;
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import org.apache.tools.zip.ZipEncoding;
-import org.apache.tools.zip.ZipEncodingHelper;
-
-/**
- * The TarInputStream reads a UNIX tar archive as an InputStream.
- * methods are provided to position at each successive entry in
- * the archive, and the read each entry as a normal input stream
- * using read().
- *
- */
-public class TarInputStream extends FilterInputStream {
- private static final int SMALL_BUFFER_SIZE = 256;
- private static final int BUFFER_SIZE = 8 * 1024;
- private static final int LARGE_BUFFER_SIZE = 32 * 1024;
- private static final int BYTE_MASK = 0xFF;
-
- private final byte[] SKIP_BUF = new byte[BUFFER_SIZE];
- private final byte[] SMALL_BUF = new byte[SMALL_BUFFER_SIZE];
-
- // CheckStyle:VisibilityModifier OFF - bc
- protected boolean debug;
- protected boolean hasHitEOF;
- protected long entrySize;
- protected long entryOffset;
- protected byte[] readBuf;
- protected TarBuffer buffer;
- protected TarEntry currEntry;
-
- /**
- * This contents of this array is not used at all in this class,
- * it is only here to avoid repreated object creation during calls
- * to the no-arg read method.
- */
- protected byte[] oneBuf;
-
- // CheckStyle:VisibilityModifier ON
-
- private final ZipEncoding encoding;
-
- /**
- * Constructor for TarInputStream.
- * @param is the input stream to use
- */
- public TarInputStream(InputStream is) {
- this(is, TarBuffer.DEFAULT_BLKSIZE, TarBuffer.DEFAULT_RCDSIZE);
- }
-
- /**
- * Constructor for TarInputStream.
- * @param is the input stream to use
- * @param encoding name of the encoding to use for file names
- */
- public TarInputStream(InputStream is, String encoding) {
- this(is, TarBuffer.DEFAULT_BLKSIZE, TarBuffer.DEFAULT_RCDSIZE, encoding);
- }
-
- /**
- * Constructor for TarInputStream.
- * @param is the input stream to use
- * @param blockSize the block size to use
- */
- public TarInputStream(InputStream is, int blockSize) {
- this(is, blockSize, TarBuffer.DEFAULT_RCDSIZE);
- }
-
- /**
- * Constructor for TarInputStream.
- * @param is the input stream to use
- * @param blockSize the block size to use
- * @param encoding name of the encoding to use for file names
- */
- public TarInputStream(InputStream is, int blockSize, String encoding) {
- this(is, blockSize, TarBuffer.DEFAULT_RCDSIZE, encoding);
- }
-
- /**
- * Constructor for TarInputStream.
- * @param is the input stream to use
- * @param blockSize the block size to use
- * @param recordSize the record size to use
- */
- public TarInputStream(InputStream is, int blockSize, int recordSize) {
- this(is, blockSize, recordSize, null);
- }
-
- /**
- * Constructor for TarInputStream.
- * @param is the input stream to use
- * @param blockSize the block size to use
- * @param recordSize the record size to use
- * @param encoding name of the encoding to use for file names
- */
- public TarInputStream(InputStream is, int blockSize, int recordSize,
- String encoding) {
- super(is);
- this.buffer = new TarBuffer(is, blockSize, recordSize);
- this.readBuf = null;
- this.oneBuf = new byte[1];
- this.debug = false;
- this.hasHitEOF = false;
- this.encoding = ZipEncodingHelper.getZipEncoding(encoding);
- }
-
- /**
- * Sets the debugging flag.
- *
- * @param debug True to turn on debugging.
- */
- public void setDebug(boolean debug) {
- this.debug = debug;
- buffer.setDebug(debug);
- }
-
- /**
- * Closes this stream. Calls the TarBuffer's close() method.
- * @throws IOException on error
- */
- @Override
- public void close() throws IOException {
- buffer.close();
- }
-
- /**
- * Get the record size being used by this stream's TarBuffer.
- *
- * @return The TarBuffer record size.
- */
- public int getRecordSize() {
- return buffer.getRecordSize();
- }
-
- /**
- * Get the available data that can be read from the current
- * entry in the archive. This does not indicate how much data
- * is left in the entire archive, only in the current entry.
- * This value is determined from the entry's size header field
- * and the amount of data already read from the current entry.
- * Integer.MAX_VALUE is returned in case more than Integer.MAX_VALUE
- * bytes are left in the current entry in the archive.
- *
- * @return The number of available bytes for the current entry.
- * @throws IOException for signature
- */
- @Override
- public int available() throws IOException {
- if (entrySize - entryOffset > Integer.MAX_VALUE) {
- return Integer.MAX_VALUE;
- }
- return (int) (entrySize - entryOffset);
- }
-
- /**
- * Skip bytes in the input buffer. This skips bytes in the
- * current entry's data, not the entire archive, and will
- * stop at the end of the current entry's data if the number
- * to skip extends beyond that point.
- *
- * @param numToSkip The number of bytes to skip.
- * @return the number actually skipped
- * @throws IOException on error
- */
- @Override
- public long skip(long numToSkip) throws IOException {
- // REVIEW
- // This is horribly inefficient, but it ensures that we
- // properly skip over bytes via the TarBuffer...
- //
- long skip = numToSkip;
- while (skip > 0) {
- int realSkip = (int) (skip > SKIP_BUF.length
- ? SKIP_BUF.length : skip);
- int numRead = read(SKIP_BUF, 0, realSkip);
- if (numRead == -1) {
- break;
- }
- skip -= numRead;
- }
- return (numToSkip - skip);
- }
-
- /**
- * Since we do not support marking just yet, we return false.
- *
- * @return False.
- */
- @Override
- public boolean markSupported() {
- return false;
- }
-
- /**
- * Since we do not support marking just yet, we do nothing.
- *
- * @param markLimit The limit to mark.
- */
- @Override
- public void mark(int markLimit) {
- }
-
- /**
- * Since we do not support marking just yet, we do nothing.
- */
- @Override
- public void reset() {
- }
-
- /**
- * Get the next entry in this tar archive. This will skip
- * over any remaining data in the current entry, if there
- * is one, and place the input stream at the header of the
- * next entry, and read the header and instantiate a new
- * TarEntry from the header bytes and return that entry.
- * If there are no more entries in the archive, null will
- * be returned to indicate that the end of the archive has
- * been reached.
- *
- * @return The next TarEntry in the archive, or null.
- * @throws IOException on error
- */
- public TarEntry getNextEntry() throws IOException {
- if (hasHitEOF) {
- return null;
- }
-
- if (currEntry != null) {
- long numToSkip = entrySize - entryOffset;
-
- if (debug) {
- System.err.println("TarInputStream: SKIP currENTRY '"
- + currEntry.getName() + "' SZ "
- + entrySize + " OFF "
- + entryOffset + " skipping "
- + numToSkip + " bytes");
- }
-
- while (numToSkip > 0) {
- long skipped = skip(numToSkip);
- if (skipped <= 0) {
- throw new RuntimeException("failed to skip current tar"
- + " entry");
- }
- numToSkip -= skipped;
- }
-
- readBuf = null;
- }
-
- byte[] headerBuf = getRecord();
-
- if (hasHitEOF) {
- currEntry = null;
- return null;
- }
-
- try {
- currEntry = new TarEntry(headerBuf, encoding);
- } catch (IllegalArgumentException e) {
- IOException ioe = new IOException("Error detected parsing the header");
- ioe.initCause(e);
- throw ioe;
- }
- if (debug) {
- System.err.println("TarInputStream: SET CURRENTRY '"
- + currEntry.getName()
- + "' size = "
- + currEntry.getSize());
- }
-
- entryOffset = 0;
- entrySize = currEntry.getSize();
-
- if (currEntry.isGNULongLinkEntry()) {
- byte[] longLinkData = getLongNameData();
- if (longLinkData == null) {
- // Bugzilla: 40334
- // Malformed tar file - long link entry name not followed by
- // entry
- return null;
- }
- currEntry.setLinkName(encoding.decode(longLinkData));
- }
-
- if (currEntry.isGNULongNameEntry()) {
- byte[] longNameData = getLongNameData();
- if (longNameData == null) {
- // Bugzilla: 40334
- // Malformed tar file - long entry name not followed by
- // entry
- return null;
- }
- currEntry.setName(encoding.decode(longNameData));
- }
-
- if (currEntry.isPaxHeader()){ // Process Pax headers
- paxHeaders();
- }
-
- if (currEntry.isGNUSparse()){ // Process sparse files
- readGNUSparse();
- }
-
- // If the size of the next element in the archive has changed
- // due to a new size being reported in the posix header
- // information, we update entrySize here so that it contains
- // the correct value.
- entrySize = currEntry.getSize();
- return currEntry;
- }
-
- /**
- * Get the next entry in this tar archive as longname data.
- *
- * @return The next entry in the archive as longname data, or null.
- * @throws IOException on error
- */
- protected byte[] getLongNameData() throws IOException {
- // read in the name
- ByteArrayOutputStream longName = new ByteArrayOutputStream();
- int length = 0;
- while ((length = read(SMALL_BUF)) >= 0) {
- longName.write(SMALL_BUF, 0, length);
- }
- getNextEntry();
- if (currEntry == null) {
- // Bugzilla: 40334
- // Malformed tar file - long entry name not followed by entry
- return null;
- }
- byte[] longNameData = longName.toByteArray();
- // remove trailing null terminator(s)
- length = longNameData.length;
- while (length > 0 && longNameData[length - 1] == 0) {
- --length;
- }
- if (length != longNameData.length) {
- byte[] l = new byte[length];
- System.arraycopy(longNameData, 0, l, 0, length);
- longNameData = l;
- }
- return longNameData;
- }
-
- /**
- * Get the next record in this tar archive. This will skip
- * over any remaining data in the current entry, if there
- * is one, and place the input stream at the header of the
- * next entry.
- * If there are no more entries in the archive, null will
- * be returned to indicate that the end of the archive has
- * been reached.
- *
- * @return The next header in the archive, or null.
- * @throws IOException on error
- */
- private byte[] getRecord() throws IOException {
- if (hasHitEOF) {
- return 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;
- }
-
- return hasHitEOF ? null : headerBuf;
- }
-
- private void paxHeaders() throws IOException{
- Map<String, String> headers = parsePaxHeaders(this);
- getNextEntry(); // Get the actual file entry
- applyPaxHeadersToCurrentEntry(headers);
- }
-
- Map<String, String> parsePaxHeaders(InputStream i) throws IOException {
- Map<String, String> headers = new HashMap<String, String>();
- // Format is "length keyword=value\n";
- while(true){ // get length
- int ch;
- int len = 0;
- int read = 0;
- while((ch = i.read()) != -1) {
- read++;
- if (ch == ' '){ // End of length string
- // Get keyword
- ByteArrayOutputStream coll = new ByteArrayOutputStream();
- while((ch = i.read()) != -1) {
- read++;
- if (ch == '='){ // end of keyword
- String keyword = coll.toString("UTF-8");
- // Get rest of entry
- final int restLen = len - read;
- byte[] rest = new byte[restLen];
- int got = 0;
- while (got < restLen && (ch = i.read()) != -1) {
- rest[got++] = (byte) ch;
- }
- if (got != restLen) {
- throw new IOException("Failed to read "
- + "Paxheader. Expected "
- + restLen
- + " bytes, read "
- + got);
- }
- // Drop trailing NL
- String value = new String(rest, 0,
- restLen - 1, "UTF-8");
- headers.put(keyword, value);
- break;
- }
- coll.write((byte) ch);
- }
- break; // Processed single header
- }
- len *= 10;
- len += ch - '0';
- }
- if (ch == -1){ // EOF
- break;
- }
- }
- return headers;
- }
-
- private void applyPaxHeadersToCurrentEntry(Map<String, String> headers) {
- /*
- * The following headers are defined for Pax.
- * atime, ctime, charset: cannot use these without changing TarEntry fields
- * mtime
- * comment
- * gid, gname
- * linkpath
- * size
- * uid,uname
- * SCHILY.devminor, SCHILY.devmajor: don't have setters/getters for those
- */
- for (Entry<String, String> ent : headers.entrySet()){
- String key = ent.getKey();
- String val = ent.getValue();
- if ("path".equals(key)){
- currEntry.setName(val);
- } else if ("linkpath".equals(key)){
- currEntry.setLinkName(val);
- } else if ("gid".equals(key)){
- currEntry.setGroupId(Long.parseLong(val));
- } else if ("gname".equals(key)){
- currEntry.setGroupName(val);
- } else if ("uid".equals(key)){
- currEntry.setUserId(Long.parseLong(val));
- } else if ("uname".equals(key)){
- currEntry.setUserName(val);
- } else if ("size".equals(key)){
- currEntry.setSize(Long.parseLong(val));
- } else if ("mtime".equals(key)){
- currEntry.setModTime((long) (Double.parseDouble(val) * 1000));
- } else if ("SCHILY.devminor".equals(key)){
- currEntry.setDevMinor(Integer.parseInt(val));
- } else if ("SCHILY.devmajor".equals(key)){
- currEntry.setDevMajor(Integer.parseInt(val));
- }
- }
- }
-
- /**
- * Adds the sparse chunks from the current entry to the sparse chunks,
- * including any additional sparse entries following the current entry.
- *
- * @throws IOException on error
- *
- * @todo Sparse files get not yet really processed.
- */
- private void readGNUSparse() throws IOException {
- /* we do not really process sparse files yet
- sparses = new ArrayList();
- sparses.addAll(currEntry.getSparses());
- */
- if (currEntry.isExtended()) {
- TarArchiveSparseEntry entry;
- do {
- byte[] headerBuf = getRecord();
- if (hasHitEOF) {
- currEntry = null;
- break;
- }
- entry = new TarArchiveSparseEntry(headerBuf);
- /* we do not really process sparse files yet
- sparses.addAll(entry.getSparses());
- */
- } while (entry.isExtended());
- }
- }
-
- /**
- * Reads a byte from the current tar archive entry.
- *
- * This method simply calls read( byte[], int, int ).
- *
- * @return The byte read, or -1 at EOF.
- * @throws IOException on error
- */
- @Override
- public int read() throws IOException {
- int num = read(oneBuf, 0, 1);
- return num == -1 ? -1 : (oneBuf[0]) & BYTE_MASK;
- }
-
- /**
- * Reads bytes from the current tar archive entry.
- *
- * This method is aware of the boundaries of the current
- * entry in the archive and will deal with them as if they
- * were this stream's start and EOF.
- *
- * @param buf The buffer into which to place bytes read.
- * @param offset The offset at which to place bytes read.
- * @param numToRead The number of bytes to read.
- * @return The number of bytes read, or -1 at EOF.
- * @throws IOException on error
- */
- @Override
- public int read(byte[] buf, int offset, int numToRead) throws IOException {
- int totalRead = 0;
-
- if (entryOffset >= entrySize) {
- return -1;
- }
-
- if ((numToRead + entryOffset) > entrySize) {
- numToRead = (int) (entrySize - entryOffset);
- }
-
- if (readBuf != null) {
- int sz = (numToRead > readBuf.length) ? readBuf.length
- : numToRead;
-
- 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) {
- // Unexpected EOF!
- 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;
- }
-
- /**
- * Copies the contents of the current tar archive entry directly into
- * an output stream.
- *
- * @param out The OutputStream into which to write the entry's data.
- * @throws IOException on error
- */
- public void copyEntryContents(OutputStream out) throws IOException {
- byte[] buf = new byte[LARGE_BUFFER_SIZE];
-
- while (true) {
- int numRead = read(buf, 0, buf.length);
-
- if (numRead == -1) {
- break;
- }
-
- out.write(buf, 0, numRead);
- }
- }
-
- /**
- * Whether this class is able to read the given entry.
- *
- * <p>May return false if the current entry is a sparse file.</p>
- */
- public boolean canReadEntryData(TarEntry te) {
- return !te.isGNUSparse();
- }
-}
-