Author: sebb Date: Mon May 10 14:14:37 2010 New Revision: 942748 URL: http://svn.apache.org/viewvc?rev=942748&view=rev Log: COMPRESS-109 - Tar implementation does not support Pax headers
Modified: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveInputStream.java Modified: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveInputStream.java URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveInputStream.java?rev=942748&r1=942747&r2=942748&view=diff ============================================================================== --- commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveInputStream.java (original) +++ commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveInputStream.java Mon May 10 14:14:37 2010 @@ -23,8 +23,15 @@ package org.apache.commons.compress.archivers.tar; +import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; + import org.apache.commons.compress.archivers.ArchiveEntry; import org.apache.commons.compress.archivers.ArchiveInputStream; import org.apache.commons.compress.utils.ArchiveUtils; @@ -216,9 +223,84 @@ public class TarArchiveInputStream exten currEntry.setName(longName.toString()); } + if (currEntry != null && currEntry.isPaxHeader()){ // Process Pax headers + paxHeaders(); + } + return currEntry; } + private void paxHeaders() throws IOException{ + BufferedReader br = new BufferedReader(new InputStreamReader(this, "UTF-8")); + 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 + 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); + } + 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)); + } + } + } + public ArchiveEntry getNextEntry() throws IOException { return getNextTarEntry(); }