/** * Whether this class is able to read the given entry. * * <p>May return false if the current entry is a sparse file. */ public boolean canReadEntryData(ArchiveEntry ae) { if (ae instanceof TarArchiveEntry) { TarArchiveEntry te = (TarArchiveEntry) ae; return !te.isGNUSparse(); } return false; }
/** * 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()); } }
/** * 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 TarArchiveEntry getNextTarEntry() throws IOException { if (hasHitEOF) { return null; } if (currEntry != null) { long numToSkip = entrySize - entryOffset; 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; } currEntry = new TarArchiveEntry(headerBuf); entryOffset = 0; entrySize = currEntry.getSize(); if (currEntry.isGNULongNameEntry()) { // read in the name StringBuffer longName = new StringBuffer(); byte[] buf = new byte[SMALL_BUFFER_SIZE]; int length = 0; while ((length = read(buf)) >= 0) { longName.append(new String(buf, 0, length)); } getNextEntry(); if (currEntry == null) { // Bugzilla: 40334 // Malformed tar file - long entry name not followed by entry return null; } // remove trailing null terminator if (longName.length() > 0 && longName.charAt(longName.length() - 1) == 0) { longName.deleteCharAt(longName.length() - 1); } currEntry.setName(longName.toString()); } if (currEntry.isPaxHeader()) { // Process Pax headers paxHeaders(); } if (currEntry.isGNUSparse()) { // Process sparse files readGNUSparse(); } return currEntry; }
private void paxHeaders() throws IOException { BufferedInputStream br = new BufferedInputStream(this); Map headers = new HashMap(); // Format is "length keyword=value\n"; while (true) { // get length int ch; int len = 0; int read = 0; while ((ch = br.read()) != -1) { read++; if (ch == ' ') { // End of length string // Get keyword StringBuffer sb = new StringBuffer(); while ((ch = br.read()) != -1) { read++; if (ch == '=') { // end of keyword String keyword = sb.toString(); // Get rest of entry byte[] cbuf = new byte[len - read]; int got = br.read(cbuf); if (got != len - read) { throw new IOException( "Failed to read Paxheader. Expected " + (len - read) + " chars, read " + got); } String value = new String(cbuf, 0, len - read - 1); // Drop trailing NL headers.put(keyword, value); break; } sb.append((char) ch); } break; // Processed single header } len *= 10; len += ch - '0'; } if (ch == -1) { // EOF break; } } getNextEntry(); // Get the actual file entry /* * The following headers are defined for Pax. * atime, ctime, mtime, charset: cannot use these without changing TarArchiveEntry fields * comment * gid, gname * linkpath * size * uid,uname */ Iterator hdrs = headers.entrySet().iterator(); while (hdrs.hasNext()) { Entry ent = (Entry) hdrs.next(); String key = (String) ent.getKey(); String val = (String) ent.getValue(); if ("path".equals(key)) { currEntry.setName(val); } else if ("linkpath".equals(key)) { currEntry.setLinkName(val); } else if ("gid".equals(key)) { currEntry.setGroupId(Integer.parseInt(val)); } else if ("gname".equals(key)) { currEntry.setGroupName(val); } else if ("uid".equals(key)) { currEntry.setUserId(Integer.parseInt(val)); } else if ("uname".equals(key)) { currEntry.setUserName(val); } else if ("size".equals(key)) { currEntry.setSize(Long.parseLong(val)); } } }
private void paxHeaders() throws IOException { Reader br = new InputStreamReader(this, "UTF-8") { @Override public void close() { // make sure GC doesn't close "this" before we are done } }; Map<String, String> headers = new HashMap<String, String>(); // Format is "length keyword=value\n"; try { while (true) { // get length int ch; int len = 0; int read = 0; while ((ch = br.read()) != -1) { read++; if (ch == ' ') { // End of length string // Get keyword StringBuffer sb = new StringBuffer(); while ((ch = br.read()) != -1) { read++; if (ch == '=') { // end of keyword String keyword = sb.toString(); // Get rest of entry char[] cbuf = new char[len - read]; int got = br.read(cbuf); if (got != len - read) { throw new IOException( "Failed to read " + "Paxheader. Expected " + (len - read) + " chars, read " + got); } // Drop trailing NL String value = new String(cbuf, 0, len - read - 1); headers.put(keyword, value); break; } sb.append((char) ch); } break; // Processed single header } len *= 10; len += ch - '0'; } if (ch == -1) { // EOF break; } } } finally { // NO-OP but makes FindBugs happy br.close(); } getNextEntry(); // Get the actual file entry /* * The following headers are defined for Pax. * atime, ctime, mtime, charset: cannot use these without changing TarArchiveEntry fields * comment * gid, gname * linkpath * size * uid,uname */ 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(Integer.parseInt(val)); } else if ("gname".equals(key)) { currEntry.setGroupName(val); } else if ("uid".equals(key)) { currEntry.setUserId(Integer.parseInt(val)); } else if ("uname".equals(key)) { currEntry.setUserName(val); } else if ("size".equals(key)) { currEntry.setSize(Long.parseLong(val)); } } }