git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@270928 13f79535-47bb-0310-9956-ffa450edef68master
@@ -51,101 +51,107 @@ import java.util.Date; | |||||
* } header; | * } header; | ||||
* </pre> | * </pre> | ||||
* | * | ||||
* @author Timothy Gerard Endres <a href="mailto:time@ice.com">time@ice.com</a> | |||||
* @author Stefano Mazzocchi <a href="mailto:stefano@apache.org"> | |||||
* stefano@apache.org</a> | |||||
* @author <a href="mailto:time@ice.com">Timothy Gerard Endres</a> | |||||
* @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a> | |||||
* @author <a href="mailto:peter@apache.org">Peter Donald</a> | |||||
*/ | */ | ||||
public class TarEntry implements TarConstants | |||||
public class TarEntry | |||||
// implements TarConstants | |||||
{ | { | ||||
/** | |||||
* The length of the name field in a header buffer. | |||||
*/ | |||||
public static final int NAMELEN = 100; | |||||
/** | /** | ||||
* The entry's modification time. | * The entry's modification time. | ||||
*/ | */ | ||||
private int checkSum; | |||||
private int m_checkSum; | |||||
/** | /** | ||||
* The entry's group name. | * The entry's group name. | ||||
*/ | */ | ||||
private int devMajor; | |||||
private int m_devMajor; | |||||
/** | /** | ||||
* The entry's major device number. | * The entry's major device number. | ||||
*/ | */ | ||||
private int devMinor; | |||||
private int m_devMinor; | |||||
/** | /** | ||||
* The entry's minor device number. | * The entry's minor device number. | ||||
*/ | */ | ||||
private File file; | |||||
private File m_file; | |||||
/** | /** | ||||
* The entry's user id. | * The entry's user id. | ||||
*/ | */ | ||||
private int groupId; | |||||
private int m_groupId; | |||||
/** | /** | ||||
* The entry's user name. | * The entry's user name. | ||||
*/ | */ | ||||
private StringBuffer groupName; | |||||
private StringBuffer m_groupName; | |||||
/** | /** | ||||
* The entry's checksum. | * The entry's checksum. | ||||
*/ | */ | ||||
private byte linkFlag; | |||||
private byte m_linkFlag; | |||||
/** | /** | ||||
* The entry's link flag. | * The entry's link flag. | ||||
*/ | */ | ||||
private StringBuffer linkName; | |||||
private StringBuffer m_linkName; | |||||
/** | /** | ||||
* The entry's link name. | * The entry's link name. | ||||
*/ | */ | ||||
private StringBuffer magic; | |||||
private StringBuffer m_magic; | |||||
/** | /** | ||||
* The entry's size. | * The entry's size. | ||||
*/ | */ | ||||
private long modTime; | |||||
private long m_modTime; | |||||
/** | /** | ||||
* The entry's name. | * The entry's name. | ||||
*/ | */ | ||||
private int mode; | |||||
private int m_mode; | |||||
private StringBuffer m_name; | |||||
private StringBuffer name; | |||||
/** | /** | ||||
* The entry's group id. | * The entry's group id. | ||||
*/ | */ | ||||
private long size; | |||||
private long m_size; | |||||
/** | /** | ||||
* The entry's permission mode. | * The entry's permission mode. | ||||
*/ | */ | ||||
private int userId; | |||||
private int m_userID; | |||||
/** | /** | ||||
* The entry's magic tag. | * The entry's magic tag. | ||||
*/ | */ | ||||
private StringBuffer userName; | |||||
private StringBuffer m_userName; | |||||
/** | /** | ||||
* Construct an entry with only a name. This allows the programmer to | * Construct an entry with only a name. This allows the programmer to | ||||
* construct the entry's header "by hand". File is set to null. | * construct the entry's header "by hand". File is set to null. | ||||
* | |||||
* @param name Description of Parameter | |||||
*/ | */ | ||||
public TarEntry( String name ) | |||||
public TarEntry( final String name ) | |||||
{ | { | ||||
this(); | this(); | ||||
boolean isDir = name.endsWith( "/" ); | |||||
this.checkSum = 0; | |||||
this.devMajor = 0; | |||||
this.devMinor = 0; | |||||
this.name = new StringBuffer( name ); | |||||
this.mode = isDir ? 040755 : 0100644; | |||||
this.linkFlag = isDir ? LF_DIR : LF_NORMAL; | |||||
this.userId = 0; | |||||
this.groupId = 0; | |||||
this.size = 0; | |||||
this.checkSum = 0; | |||||
this.modTime = ( new Date() ).getTime() / 1000; | |||||
this.linkName = new StringBuffer( "" ); | |||||
this.userName = new StringBuffer( "" ); | |||||
this.groupName = new StringBuffer( "" ); | |||||
this.devMajor = 0; | |||||
this.devMinor = 0; | |||||
final boolean isDir = name.endsWith( "/" ); | |||||
m_name = new StringBuffer( name ); | |||||
m_mode = isDir ? 040755 : 0100644; | |||||
m_linkFlag = isDir ? TarConstants.LF_DIR : TarConstants.LF_NORMAL; | |||||
m_modTime = ( new Date() ).getTime() / 1000; | |||||
m_linkName = new StringBuffer( "" ); | |||||
m_userName = new StringBuffer( "" ); | |||||
m_groupName = new StringBuffer( "" ); | |||||
} | } | ||||
/** | /** | ||||
@@ -154,10 +160,10 @@ public class TarEntry implements TarConstants | |||||
* @param name Description of Parameter | * @param name Description of Parameter | ||||
* @param linkFlag Description of Parameter | * @param linkFlag Description of Parameter | ||||
*/ | */ | ||||
public TarEntry( String name, byte linkFlag ) | |||||
public TarEntry( final String name, final byte linkFlag ) | |||||
{ | { | ||||
this( name ); | this( name ); | ||||
this.linkFlag = linkFlag; | |||||
m_linkFlag = linkFlag; | |||||
} | } | ||||
/** | /** | ||||
@@ -166,33 +172,32 @@ public class TarEntry implements TarConstants | |||||
* | * | ||||
* @param file The file that the entry represents. | * @param file The file that the entry represents. | ||||
*/ | */ | ||||
public TarEntry( File file ) | |||||
public TarEntry( final File file ) | |||||
{ | { | ||||
this(); | this(); | ||||
this.file = file; | |||||
m_file = file; | |||||
String name = file.getPath(); | String name = file.getPath(); | ||||
String osname = System.getProperty( "os.name" ); | |||||
final String osname = System.getProperty( "os.name" ); | |||||
if( osname != null ) | if( osname != null ) | ||||
{ | { | ||||
// Strip off drive letters! | // Strip off drive letters! | ||||
// REVIEW Would a better check be "(File.separator == '\')"? | // REVIEW Would a better check be "(File.separator == '\')"? | ||||
String win32Prefix = "Windows"; | |||||
String prefix = osname.substring( 0, win32Prefix.length() ); | |||||
final String win32Prefix = "Windows"; | |||||
final String prefix = osname.substring( 0, win32Prefix.length() ); | |||||
if( prefix.equalsIgnoreCase( win32Prefix ) ) | if( prefix.equalsIgnoreCase( win32Prefix ) ) | ||||
{ | { | ||||
if( name.length() > 2 ) | if( name.length() > 2 ) | ||||
{ | { | ||||
char ch1 = name.charAt( 0 ); | |||||
char ch2 = name.charAt( 1 ); | |||||
final char ch1 = name.charAt( 0 ); | |||||
final char ch2 = name.charAt( 1 ); | |||||
if( ch2 == ':' | |||||
&& ( ( ch1 >= 'a' && ch1 <= 'z' ) | |||||
|| ( ch1 >= 'A' && ch1 <= 'Z' ) ) ) | |||||
if( ch2 == ':' && | |||||
( ( ch1 >= 'a' && ch1 <= 'z' ) || | |||||
( ch1 >= 'A' && ch1 <= 'Z' ) ) ) | |||||
{ | { | ||||
name = name.substring( 2 ); | name = name.substring( 2 ); | ||||
} | } | ||||
@@ -200,7 +205,7 @@ public class TarEntry implements TarConstants | |||||
} | } | ||||
else if( osname.toLowerCase().indexOf( "netware" ) > -1 ) | else if( osname.toLowerCase().indexOf( "netware" ) > -1 ) | ||||
{ | { | ||||
int colon = name.indexOf( ':' ); | |||||
final int colon = name.indexOf( ':' ); | |||||
if( colon != -1 ) | if( colon != -1 ) | ||||
{ | { | ||||
name = name.substring( colon + 1 ); | name = name.substring( colon + 1 ); | ||||
@@ -218,68 +223,60 @@ public class TarEntry implements TarConstants | |||||
name = name.substring( 1 ); | name = name.substring( 1 ); | ||||
} | } | ||||
this.linkName = new StringBuffer( "" ); | |||||
this.name = new StringBuffer( name ); | |||||
m_linkName = new StringBuffer( "" ); | |||||
m_name = new StringBuffer( name ); | |||||
if( file.isDirectory() ) | if( file.isDirectory() ) | ||||
{ | { | ||||
this.mode = 040755; | |||||
this.linkFlag = LF_DIR; | |||||
m_mode = 040755; | |||||
m_linkFlag = TarConstants.LF_DIR; | |||||
if( this.name.charAt( this.name.length() - 1 ) != '/' ) | |||||
if( m_name.charAt( m_name.length() - 1 ) != '/' ) | |||||
{ | { | ||||
this.name.append( "/" ); | |||||
m_name.append( "/" ); | |||||
} | } | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
this.mode = 0100644; | |||||
this.linkFlag = LF_NORMAL; | |||||
m_mode = 0100644; | |||||
m_linkFlag = TarConstants.LF_NORMAL; | |||||
} | } | ||||
this.size = file.length(); | |||||
this.modTime = file.lastModified() / 1000; | |||||
this.checkSum = 0; | |||||
this.devMajor = 0; | |||||
this.devMinor = 0; | |||||
m_size = file.length(); | |||||
m_modTime = file.lastModified() / 1000; | |||||
m_checkSum = 0; | |||||
m_devMajor = 0; | |||||
m_devMinor = 0; | |||||
} | } | ||||
/** | /** | ||||
* Construct an entry from an archive's header bytes. File is set to null. | * Construct an entry from an archive's header bytes. File is set to null. | ||||
* | * | ||||
* @param headerBuf The header bytes from a tar archive entry. | |||||
* @param header The header bytes from a tar archive entry. | |||||
*/ | */ | ||||
public TarEntry( byte[] headerBuf ) | |||||
public TarEntry( final byte[] header ) | |||||
{ | { | ||||
this(); | this(); | ||||
this.parseTarHeader( headerBuf ); | |||||
parseTarHeader( header ); | |||||
} | } | ||||
/** | |||||
* The entry's file reference | |||||
*/ | |||||
/** | /** | ||||
* Construct an empty entry and prepares the header values. | * Construct an empty entry and prepares the header values. | ||||
*/ | */ | ||||
private TarEntry() | private TarEntry() | ||||
{ | { | ||||
this.magic = new StringBuffer( TMAGIC ); | |||||
this.name = new StringBuffer(); | |||||
this.linkName = new StringBuffer(); | |||||
m_magic = new StringBuffer( TarConstants.TMAGIC ); | |||||
m_name = new StringBuffer(); | |||||
m_linkName = new StringBuffer(); | |||||
String user = System.getProperty( "user.name", "" ); | String user = System.getProperty( "user.name", "" ); | ||||
if( user.length() > 31 ) | if( user.length() > 31 ) | ||||
{ | { | ||||
user = user.substring( 0, 31 ); | user = user.substring( 0, 31 ); | ||||
} | } | ||||
this.userId = 0; | |||||
this.groupId = 0; | |||||
this.userName = new StringBuffer( user ); | |||||
this.groupName = new StringBuffer( "" ); | |||||
this.file = null; | |||||
m_userName = new StringBuffer( user ); | |||||
m_groupName = new StringBuffer( "" ); | |||||
} | } | ||||
/** | /** | ||||
@@ -287,9 +284,9 @@ public class TarEntry implements TarConstants | |||||
* | * | ||||
* @param groupId This entry's new group id. | * @param groupId This entry's new group id. | ||||
*/ | */ | ||||
public void setGroupId( int groupId ) | |||||
public void setGroupId( final int groupId ) | |||||
{ | { | ||||
this.groupId = groupId; | |||||
m_groupId = groupId; | |||||
} | } | ||||
/** | /** | ||||
@@ -297,21 +294,9 @@ public class TarEntry implements TarConstants | |||||
* | * | ||||
* @param groupName This entry's new group name. | * @param groupName This entry's new group name. | ||||
*/ | */ | ||||
public void setGroupName( String groupName ) | |||||
{ | |||||
this.groupName = new StringBuffer( groupName ); | |||||
} | |||||
/** | |||||
* Convenience method to set this entry's group and user ids. | |||||
* | |||||
* @param userId This entry's new user id. | |||||
* @param groupId This entry's new group id. | |||||
*/ | |||||
public void setIds( int userId, int groupId ) | |||||
public void setGroupName( final String groupName ) | |||||
{ | { | ||||
this.setUserId( userId ); | |||||
this.setGroupId( groupId ); | |||||
m_groupName = new StringBuffer( groupName ); | |||||
} | } | ||||
/** | /** | ||||
@@ -320,9 +305,9 @@ public class TarEntry implements TarConstants | |||||
* | * | ||||
* @param time This entry's new modification time. | * @param time This entry's new modification time. | ||||
*/ | */ | ||||
public void setModTime( long time ) | |||||
public void setModTime( final long time ) | |||||
{ | { | ||||
this.modTime = time / 1000; | |||||
m_modTime = time / 1000; | |||||
} | } | ||||
/** | /** | ||||
@@ -330,9 +315,9 @@ public class TarEntry implements TarConstants | |||||
* | * | ||||
* @param time This entry's new modification time. | * @param time This entry's new modification time. | ||||
*/ | */ | ||||
public void setModTime( Date time ) | |||||
public void setModTime( final Date time ) | |||||
{ | { | ||||
this.modTime = time.getTime() / 1000; | |||||
m_modTime = time.getTime() / 1000; | |||||
} | } | ||||
/** | /** | ||||
@@ -340,9 +325,9 @@ public class TarEntry implements TarConstants | |||||
* | * | ||||
* @param mode The new Mode value | * @param mode The new Mode value | ||||
*/ | */ | ||||
public void setMode( int mode ) | |||||
public void setMode( final int mode ) | |||||
{ | { | ||||
this.mode = mode; | |||||
m_mode = mode; | |||||
} | } | ||||
/** | /** | ||||
@@ -350,21 +335,9 @@ public class TarEntry implements TarConstants | |||||
* | * | ||||
* @param name This entry's new name. | * @param name This entry's new name. | ||||
*/ | */ | ||||
public void setName( String name ) | |||||
public void setName( final String name ) | |||||
{ | { | ||||
this.name = new StringBuffer( name ); | |||||
} | |||||
/** | |||||
* Convenience method to set this entry's group and user names. | |||||
* | |||||
* @param userName This entry's new user name. | |||||
* @param groupName This entry's new group name. | |||||
*/ | |||||
public void setNames( String userName, String groupName ) | |||||
{ | |||||
this.setUserName( userName ); | |||||
this.setGroupName( groupName ); | |||||
m_name = new StringBuffer( name ); | |||||
} | } | ||||
/** | /** | ||||
@@ -372,9 +345,9 @@ public class TarEntry implements TarConstants | |||||
* | * | ||||
* @param size This entry's new file size. | * @param size This entry's new file size. | ||||
*/ | */ | ||||
public void setSize( long size ) | |||||
public void setSize( final long size ) | |||||
{ | { | ||||
this.size = size; | |||||
m_size = size; | |||||
} | } | ||||
/** | /** | ||||
@@ -382,9 +355,9 @@ public class TarEntry implements TarConstants | |||||
* | * | ||||
* @param userId This entry's new user id. | * @param userId This entry's new user id. | ||||
*/ | */ | ||||
public void setUserId( int userId ) | |||||
public void setUserId( final int userId ) | |||||
{ | { | ||||
this.userId = userId; | |||||
m_userID = userId; | |||||
} | } | ||||
/** | /** | ||||
@@ -392,9 +365,9 @@ public class TarEntry implements TarConstants | |||||
* | * | ||||
* @param userName This entry's new user name. | * @param userName This entry's new user name. | ||||
*/ | */ | ||||
public void setUserName( String userName ) | |||||
public void setUserName( final String userName ) | |||||
{ | { | ||||
this.userName = new StringBuffer( userName ); | |||||
m_userName = new StringBuffer( userName ); | |||||
} | } | ||||
/** | /** | ||||
@@ -405,17 +378,17 @@ public class TarEntry implements TarConstants | |||||
*/ | */ | ||||
public TarEntry[] getDirectoryEntries() | public TarEntry[] getDirectoryEntries() | ||||
{ | { | ||||
if( this.file == null || !this.file.isDirectory() ) | |||||
if( null == m_file || !m_file.isDirectory() ) | |||||
{ | { | ||||
return new TarEntry[ 0 ]; | return new TarEntry[ 0 ]; | ||||
} | } | ||||
String[] list = this.file.list(); | |||||
TarEntry[] result = new TarEntry[ list.length ]; | |||||
final String[] list = m_file.list(); | |||||
final TarEntry[] result = new TarEntry[ list.length ]; | |||||
for( int i = 0; i < list.length; ++i ) | for( int i = 0; i < list.length; ++i ) | ||||
{ | { | ||||
result[ i ] = new TarEntry( new File( this.file, list[ i ] ) ); | |||||
result[ i ] = new TarEntry( new File( m_file, list[ i ] ) ); | |||||
} | } | ||||
return result; | return result; | ||||
@@ -428,7 +401,7 @@ public class TarEntry implements TarConstants | |||||
*/ | */ | ||||
public File getFile() | public File getFile() | ||||
{ | { | ||||
return this.file; | |||||
return m_file; | |||||
} | } | ||||
/** | /** | ||||
@@ -438,7 +411,7 @@ public class TarEntry implements TarConstants | |||||
*/ | */ | ||||
public int getGroupId() | public int getGroupId() | ||||
{ | { | ||||
return this.groupId; | |||||
return m_groupId; | |||||
} | } | ||||
/** | /** | ||||
@@ -448,7 +421,7 @@ public class TarEntry implements TarConstants | |||||
*/ | */ | ||||
public String getGroupName() | public String getGroupName() | ||||
{ | { | ||||
return this.groupName.toString(); | |||||
return m_groupName.toString(); | |||||
} | } | ||||
/** | /** | ||||
@@ -458,7 +431,7 @@ public class TarEntry implements TarConstants | |||||
*/ | */ | ||||
public Date getModTime() | public Date getModTime() | ||||
{ | { | ||||
return new Date( this.modTime * 1000 ); | |||||
return new Date( m_modTime * 1000 ); | |||||
} | } | ||||
/** | /** | ||||
@@ -468,7 +441,7 @@ public class TarEntry implements TarConstants | |||||
*/ | */ | ||||
public int getMode() | public int getMode() | ||||
{ | { | ||||
return this.mode; | |||||
return m_mode; | |||||
} | } | ||||
/** | /** | ||||
@@ -478,7 +451,7 @@ public class TarEntry implements TarConstants | |||||
*/ | */ | ||||
public String getName() | public String getName() | ||||
{ | { | ||||
return this.name.toString(); | |||||
return m_name.toString(); | |||||
} | } | ||||
/** | /** | ||||
@@ -488,7 +461,7 @@ public class TarEntry implements TarConstants | |||||
*/ | */ | ||||
public long getSize() | public long getSize() | ||||
{ | { | ||||
return this.size; | |||||
return m_size; | |||||
} | } | ||||
/** | /** | ||||
@@ -498,7 +471,7 @@ public class TarEntry implements TarConstants | |||||
*/ | */ | ||||
public int getUserId() | public int getUserId() | ||||
{ | { | ||||
return this.userId; | |||||
return m_userID; | |||||
} | } | ||||
/** | /** | ||||
@@ -508,7 +481,7 @@ public class TarEntry implements TarConstants | |||||
*/ | */ | ||||
public String getUserName() | public String getUserName() | ||||
{ | { | ||||
return this.userName.toString(); | |||||
return m_userName.toString(); | |||||
} | } | ||||
/** | /** | ||||
@@ -516,12 +489,12 @@ public class TarEntry implements TarConstants | |||||
* is determined by the name of the descendant starting with this entry's | * is determined by the name of the descendant starting with this entry's | ||||
* name. | * name. | ||||
* | * | ||||
* @param desc Entry to be checked as a descendent of this. | |||||
* @return True if entry is a descendant of this. | |||||
* @param desc Entry to be checked as a descendent of | |||||
* @return True if entry is a descendant of | |||||
*/ | */ | ||||
public boolean isDescendent( TarEntry desc ) | |||||
public boolean isDescendent( final TarEntry desc ) | |||||
{ | { | ||||
return desc.getName().startsWith( this.getName() ); | |||||
return desc.getName().startsWith( getName() ); | |||||
} | } | ||||
/** | /** | ||||
@@ -531,17 +504,17 @@ public class TarEntry implements TarConstants | |||||
*/ | */ | ||||
public boolean isDirectory() | public boolean isDirectory() | ||||
{ | { | ||||
if( this.file != null ) | |||||
if( m_file != null ) | |||||
{ | { | ||||
return this.file.isDirectory(); | |||||
return m_file.isDirectory(); | |||||
} | } | ||||
if( this.linkFlag == LF_DIR ) | |||||
if( m_linkFlag == TarConstants.LF_DIR ) | |||||
{ | { | ||||
return true; | return true; | ||||
} | } | ||||
if( this.getName().endsWith( "/" ) ) | |||||
if( getName().endsWith( "/" ) ) | |||||
{ | { | ||||
return true; | return true; | ||||
} | } | ||||
@@ -556,21 +529,20 @@ public class TarEntry implements TarConstants | |||||
*/ | */ | ||||
public boolean isGNULongNameEntry() | public boolean isGNULongNameEntry() | ||||
{ | { | ||||
return linkFlag == LF_GNUTYPE_LONGNAME && | |||||
name.toString().equals( GNU_LONGLINK ); | |||||
return m_linkFlag == TarConstants.LF_GNUTYPE_LONGNAME && | |||||
m_name.toString().equals( TarConstants.GNU_LONGLINK ); | |||||
} | } | ||||
/** | /** | ||||
* Determine if the two entries are equal. Equality is determined by the | * Determine if the two entries are equal. Equality is determined by the | ||||
* header names being equal. | * header names being equal. | ||||
* | * | ||||
* @param it Description of Parameter | |||||
* @return it Entry to be checked for equality. | |||||
* @param other Entry to be checked for equality. | |||||
* @return True if the entries are equal. | * @return True if the entries are equal. | ||||
*/ | */ | ||||
public boolean equals( TarEntry it ) | |||||
public boolean equals( final TarEntry other ) | |||||
{ | { | ||||
return this.getName().equals( it.getName() ); | |||||
return getName().equals( other.getName() ); | |||||
} | } | ||||
/** | /** | ||||
@@ -578,36 +550,36 @@ public class TarEntry implements TarConstants | |||||
* | * | ||||
* @param header The tar entry header buffer to get information from. | * @param header The tar entry header buffer to get information from. | ||||
*/ | */ | ||||
public void parseTarHeader( byte[] header ) | |||||
private void parseTarHeader( final byte[] header ) | |||||
{ | { | ||||
int offset = 0; | int offset = 0; | ||||
this.name = TarUtils.parseName( header, offset, NAMELEN ); | |||||
m_name = TarUtils.parseName( header, offset, NAMELEN ); | |||||
offset += NAMELEN; | offset += NAMELEN; | ||||
this.mode = (int)TarUtils.parseOctal( header, offset, MODELEN ); | |||||
offset += MODELEN; | |||||
this.userId = (int)TarUtils.parseOctal( header, offset, UIDLEN ); | |||||
offset += UIDLEN; | |||||
this.groupId = (int)TarUtils.parseOctal( header, offset, GIDLEN ); | |||||
offset += GIDLEN; | |||||
this.size = TarUtils.parseOctal( header, offset, SIZELEN ); | |||||
offset += SIZELEN; | |||||
this.modTime = TarUtils.parseOctal( header, offset, MODTIMELEN ); | |||||
offset += MODTIMELEN; | |||||
this.checkSum = (int)TarUtils.parseOctal( header, offset, CHKSUMLEN ); | |||||
offset += CHKSUMLEN; | |||||
this.linkFlag = header[ offset++ ]; | |||||
this.linkName = TarUtils.parseName( header, offset, NAMELEN ); | |||||
m_mode = (int)TarUtils.parseOctal( header, offset, TarConstants.MODELEN ); | |||||
offset += TarConstants.MODELEN; | |||||
m_userID = (int)TarUtils.parseOctal( header, offset, TarConstants.UIDLEN ); | |||||
offset += TarConstants.UIDLEN; | |||||
m_groupId = (int)TarUtils.parseOctal( header, offset, TarConstants.GIDLEN ); | |||||
offset += TarConstants.GIDLEN; | |||||
m_size = TarUtils.parseOctal( header, offset, TarConstants.SIZELEN ); | |||||
offset += TarConstants.SIZELEN; | |||||
m_modTime = TarUtils.parseOctal( header, offset, TarConstants.MODTIMELEN ); | |||||
offset += TarConstants.MODTIMELEN; | |||||
m_checkSum = (int)TarUtils.parseOctal( header, offset, TarConstants.CHKSUMLEN ); | |||||
offset += TarConstants.CHKSUMLEN; | |||||
m_linkFlag = header[ offset++ ]; | |||||
m_linkName = TarUtils.parseName( header, offset, NAMELEN ); | |||||
offset += NAMELEN; | offset += NAMELEN; | ||||
this.magic = TarUtils.parseName( header, offset, MAGICLEN ); | |||||
offset += MAGICLEN; | |||||
this.userName = TarUtils.parseName( header, offset, UNAMELEN ); | |||||
offset += UNAMELEN; | |||||
this.groupName = TarUtils.parseName( header, offset, GNAMELEN ); | |||||
offset += GNAMELEN; | |||||
this.devMajor = (int)TarUtils.parseOctal( header, offset, DEVLEN ); | |||||
offset += DEVLEN; | |||||
this.devMinor = (int)TarUtils.parseOctal( header, offset, DEVLEN ); | |||||
m_magic = TarUtils.parseName( header, offset, TarConstants.MAGICLEN ); | |||||
offset += TarConstants.MAGICLEN; | |||||
m_userName = TarUtils.parseName( header, offset, TarConstants.UNAMELEN ); | |||||
offset += TarConstants.UNAMELEN; | |||||
m_groupName = TarUtils.parseName( header, offset, TarConstants.GNAMELEN ); | |||||
offset += TarConstants.GNAMELEN; | |||||
m_devMajor = (int)TarUtils.parseOctal( header, offset, TarConstants.DEVLEN ); | |||||
offset += TarConstants.DEVLEN; | |||||
m_devMinor = (int)TarUtils.parseOctal( header, offset, TarConstants.DEVLEN ); | |||||
} | } | ||||
/** | /** | ||||
@@ -615,39 +587,37 @@ public class TarEntry implements TarConstants | |||||
* | * | ||||
* @param outbuf The tar entry header buffer to fill in. | * @param outbuf The tar entry header buffer to fill in. | ||||
*/ | */ | ||||
public void writeEntryHeader( byte[] outbuf ) | |||||
public void writeEntryHeader( final byte[] buffer ) | |||||
{ | { | ||||
int offset = 0; | int offset = 0; | ||||
offset = TarUtils.getNameBytes( this.name, outbuf, offset, NAMELEN ); | |||||
offset = TarUtils.getOctalBytes( this.mode, outbuf, offset, MODELEN ); | |||||
offset = TarUtils.getOctalBytes( this.userId, outbuf, offset, UIDLEN ); | |||||
offset = TarUtils.getOctalBytes( this.groupId, outbuf, offset, GIDLEN ); | |||||
offset = TarUtils.getLongOctalBytes( this.size, outbuf, offset, SIZELEN ); | |||||
offset = TarUtils.getLongOctalBytes( this.modTime, outbuf, offset, MODTIMELEN ); | |||||
offset = TarUtils.getNameBytes( m_name, buffer, offset, NAMELEN ); | |||||
offset = TarUtils.getOctalBytes( m_mode, buffer, offset, TarConstants.MODELEN ); | |||||
offset = TarUtils.getOctalBytes( m_userID, buffer, offset, TarConstants.UIDLEN ); | |||||
offset = TarUtils.getOctalBytes( m_groupId, buffer, offset, TarConstants.GIDLEN ); | |||||
offset = TarUtils.getLongOctalBytes( m_size, buffer, offset, TarConstants.SIZELEN ); | |||||
offset = TarUtils.getLongOctalBytes( m_modTime, buffer, offset, TarConstants.MODTIMELEN ); | |||||
int csOffset = offset; | |||||
for( int c = 0; c < CHKSUMLEN; ++c ) | |||||
final int checkSumOffset = offset; | |||||
for( int i = 0; i < TarConstants.CHKSUMLEN; ++i ) | |||||
{ | { | ||||
outbuf[ offset++ ] = (byte)' '; | |||||
buffer[ offset++ ] = (byte)' '; | |||||
} | } | ||||
outbuf[ offset++ ] = this.linkFlag; | |||||
offset = TarUtils.getNameBytes( this.linkName, outbuf, offset, NAMELEN ); | |||||
offset = TarUtils.getNameBytes( this.magic, outbuf, offset, MAGICLEN ); | |||||
offset = TarUtils.getNameBytes( this.userName, outbuf, offset, UNAMELEN ); | |||||
offset = TarUtils.getNameBytes( this.groupName, outbuf, offset, GNAMELEN ); | |||||
offset = TarUtils.getOctalBytes( this.devMajor, outbuf, offset, DEVLEN ); | |||||
offset = TarUtils.getOctalBytes( this.devMinor, outbuf, offset, DEVLEN ); | |||||
buffer[ offset++ ] = m_linkFlag; | |||||
offset = TarUtils.getNameBytes( m_linkName, buffer, offset, NAMELEN ); | |||||
offset = TarUtils.getNameBytes( m_magic, buffer, offset, TarConstants.MAGICLEN ); | |||||
offset = TarUtils.getNameBytes( m_userName, buffer, offset, TarConstants.UNAMELEN ); | |||||
offset = TarUtils.getNameBytes( m_groupName, buffer, offset, TarConstants.GNAMELEN ); | |||||
offset = TarUtils.getOctalBytes( m_devMajor, buffer, offset, TarConstants.DEVLEN ); | |||||
offset = TarUtils.getOctalBytes( m_devMinor, buffer, offset, TarConstants.DEVLEN ); | |||||
while( offset < outbuf.length ) | |||||
while( offset < buffer.length ) | |||||
{ | { | ||||
outbuf[ offset++ ] = 0; | |||||
buffer[ offset++ ] = 0; | |||||
} | } | ||||
long checkSum = TarUtils.computeCheckSum( outbuf ); | |||||
TarUtils.getCheckSumOctalBytes( checkSum, outbuf, csOffset, CHKSUMLEN ); | |||||
final long checkSum = TarUtils.computeCheckSum( buffer ); | |||||
TarUtils.getCheckSumOctalBytes( checkSum, buffer, checkSumOffset, TarConstants.CHKSUMLEN ); | |||||
} | } | ||||
} | } |
@@ -17,41 +17,40 @@ import java.io.OutputStream; | |||||
* provided to position at each successive entry in the archive, and the read | * provided to position at each successive entry in the archive, and the read | ||||
* each entry as a normal input stream using read(). | * each entry as a normal input stream using read(). | ||||
* | * | ||||
* @author Timothy Gerard Endres <a href="mailto:time@ice.com">time@ice.com</a> | |||||
* @author Stefano Mazzocchi <a href="mailto:stefano@apache.org"> | |||||
* stefano@apache.org</a> | |||||
* @author <a href="mailto:time@ice.com">Timothy Gerard Endres</a> | |||||
* @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a> | |||||
* @author <a href="mailto:peter@apache.org">Peter Donald</a> | |||||
*/ | */ | ||||
public class TarInputStream extends FilterInputStream | |||||
public class TarInputStream | |||||
extends FilterInputStream | |||||
{ | { | ||||
protected TarBuffer buffer; | |||||
protected TarEntry currEntry; | |||||
protected boolean debug; | |||||
protected int entryOffset; | |||||
protected int entrySize; | |||||
protected boolean hasHitEOF; | |||||
protected byte[] oneBuf; | |||||
protected byte[] readBuf; | |||||
public TarInputStream( InputStream is ) | |||||
private TarBuffer m_buffer; | |||||
private TarEntry m_currEntry; | |||||
private boolean m_debug; | |||||
private int m_entryOffset; | |||||
private int m_entrySize; | |||||
private boolean m_hasHitEOF; | |||||
private byte[] m_oneBuf; | |||||
private byte[] m_readBuf; | |||||
public TarInputStream( final InputStream input ) | |||||
{ | { | ||||
this( is, TarBuffer.DEFAULT_BLKSIZE, TarBuffer.DEFAULT_RCDSIZE ); | |||||
this( input, TarBuffer.DEFAULT_BLKSIZE, TarBuffer.DEFAULT_RCDSIZE ); | |||||
} | } | ||||
public TarInputStream( InputStream is, int blockSize ) | |||||
public TarInputStream( final InputStream input, final int blockSize ) | |||||
{ | { | ||||
this( is, blockSize, TarBuffer.DEFAULT_RCDSIZE ); | |||||
this( input, blockSize, TarBuffer.DEFAULT_RCDSIZE ); | |||||
} | } | ||||
public TarInputStream( InputStream is, int blockSize, int recordSize ) | |||||
public TarInputStream( final InputStream input, | |||||
final int blockSize, | |||||
final int recordSize ) | |||||
{ | { | ||||
super( is ); | |||||
super( input ); | |||||
this.buffer = new TarBuffer( is, blockSize, recordSize ); | |||||
this.readBuf = null; | |||||
this.oneBuf = new byte[ 1 ]; | |||||
this.debug = false; | |||||
this.hasHitEOF = false; | |||||
m_buffer = new TarBuffer( input, blockSize, recordSize ); | |||||
m_oneBuf = new byte[ 1 ]; | |||||
} | } | ||||
/** | /** | ||||
@@ -59,10 +58,10 @@ public class TarInputStream extends FilterInputStream | |||||
* | * | ||||
* @param debug The new Debug value | * @param debug The new Debug value | ||||
*/ | */ | ||||
public void setDebug( boolean debug ) | |||||
public void setDebug( final boolean debug ) | |||||
{ | { | ||||
this.debug = debug; | |||||
this.buffer.setDebug( debug ); | |||||
m_debug = debug; | |||||
m_buffer.setDebug( debug ); | |||||
} | } | ||||
/** | /** | ||||
@@ -79,119 +78,113 @@ public class TarInputStream extends FilterInputStream | |||||
public TarEntry getNextEntry() | public TarEntry getNextEntry() | ||||
throws IOException | throws IOException | ||||
{ | { | ||||
if( this.hasHitEOF ) | |||||
if( m_hasHitEOF ) | |||||
{ | { | ||||
return null; | return null; | ||||
} | } | ||||
if( this.currEntry != null ) | |||||
if( m_currEntry != null ) | |||||
{ | { | ||||
int numToSkip = this.entrySize - this.entryOffset; | |||||
final int numToSkip = m_entrySize - m_entryOffset; | |||||
if( this.debug ) | |||||
if( m_debug ) | |||||
{ | { | ||||
System.err.println( "TarInputStream: SKIP currENTRY '" | |||||
+ this.currEntry.getName() + "' SZ " | |||||
+ this.entrySize + " OFF " | |||||
+ this.entryOffset + " skipping " | |||||
+ numToSkip + " bytes" ); | |||||
final String message = "TarInputStream: SKIP currENTRY '" + | |||||
m_currEntry.getName() + "' SZ " + m_entrySize + | |||||
" OFF " + m_entryOffset + " skipping " + numToSkip + " bytes"; | |||||
debug( message ); | |||||
} | } | ||||
if( numToSkip > 0 ) | if( numToSkip > 0 ) | ||||
{ | { | ||||
this.skip( numToSkip ); | |||||
skip( numToSkip ); | |||||
} | } | ||||
this.readBuf = null; | |||||
m_readBuf = null; | |||||
} | } | ||||
byte[] headerBuf = this.buffer.readRecord(); | |||||
final byte[] headerBuf = m_buffer.readRecord(); | |||||
if( headerBuf == null ) | if( headerBuf == null ) | ||||
{ | { | ||||
if( this.debug ) | |||||
if( m_debug ) | |||||
{ | { | ||||
System.err.println( "READ NULL RECORD" ); | |||||
debug( "READ NULL RECORD" ); | |||||
} | } | ||||
this.hasHitEOF = true; | |||||
m_hasHitEOF = true; | |||||
} | } | ||||
else if( this.buffer.isEOFRecord( headerBuf ) ) | |||||
else if( m_buffer.isEOFRecord( headerBuf ) ) | |||||
{ | { | ||||
if( this.debug ) | |||||
if( m_debug ) | |||||
{ | { | ||||
System.err.println( "READ EOF RECORD" ); | |||||
debug( "READ EOF RECORD" ); | |||||
} | } | ||||
this.hasHitEOF = true; | |||||
m_hasHitEOF = true; | |||||
} | } | ||||
if( this.hasHitEOF ) | |||||
if( m_hasHitEOF ) | |||||
{ | { | ||||
this.currEntry = null; | |||||
m_currEntry = null; | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
this.currEntry = new TarEntry( headerBuf ); | |||||
m_currEntry = new TarEntry( headerBuf ); | |||||
if( !( headerBuf[ 257 ] == 'u' && headerBuf[ 258 ] == 's' | |||||
&& headerBuf[ 259 ] == 't' && headerBuf[ 260 ] == 'a' | |||||
&& headerBuf[ 261 ] == 'r' ) ) | |||||
if( !( headerBuf[ 257 ] == 'u' && headerBuf[ 258 ] == 's' && | |||||
headerBuf[ 259 ] == 't' && headerBuf[ 260 ] == 'a' && | |||||
headerBuf[ 261 ] == 'r' ) ) | |||||
{ | { | ||||
this.entrySize = 0; | |||||
this.entryOffset = 0; | |||||
this.currEntry = null; | |||||
throw new IOException( "bad header in block " | |||||
+ this.buffer.getCurrentBlockNum() | |||||
+ " record " | |||||
+ this.buffer.getCurrentRecordNum() | |||||
+ ", " + | |||||
"header magic is not 'ustar', but '" | |||||
+ headerBuf[ 257 ] | |||||
+ headerBuf[ 258 ] | |||||
+ headerBuf[ 259 ] | |||||
+ headerBuf[ 260 ] | |||||
+ headerBuf[ 261 ] | |||||
+ "', or (dec) " | |||||
+ ( (int)headerBuf[ 257 ] ) | |||||
+ ", " | |||||
+ ( (int)headerBuf[ 258 ] ) | |||||
+ ", " | |||||
+ ( (int)headerBuf[ 259 ] ) | |||||
+ ", " | |||||
+ ( (int)headerBuf[ 260 ] ) | |||||
+ ", " | |||||
+ ( (int)headerBuf[ 261 ] ) ); | |||||
m_entrySize = 0; | |||||
m_entryOffset = 0; | |||||
m_currEntry = null; | |||||
final String message = "bad header in block " + | |||||
m_buffer.getCurrentBlockNum() + | |||||
" record " + m_buffer.getCurrentRecordNum() + ", " + | |||||
"header magic is not 'ustar', but '" + | |||||
headerBuf[ 257 ] + | |||||
headerBuf[ 258 ] + | |||||
headerBuf[ 259 ] + | |||||
headerBuf[ 260 ] + | |||||
headerBuf[ 261 ] + | |||||
"', or (dec) " + | |||||
( (int)headerBuf[ 257 ] ) + ", " + | |||||
( (int)headerBuf[ 258 ] ) + ", " + | |||||
( (int)headerBuf[ 259 ] ) + ", " + | |||||
( (int)headerBuf[ 260 ] ) + ", " + | |||||
( (int)headerBuf[ 261 ] ); | |||||
throw new IOException( message ); | |||||
} | } | ||||
if( this.debug ) | |||||
if( m_debug ) | |||||
{ | { | ||||
System.err.println( "TarInputStream: SET CURRENTRY '" | |||||
+ this.currEntry.getName() | |||||
+ "' size = " | |||||
+ this.currEntry.getSize() ); | |||||
final String message = "TarInputStream: SET CURRENTRY '" + | |||||
m_currEntry.getName() + "' size = " + m_currEntry.getSize(); | |||||
debug( message ); | |||||
} | } | ||||
this.entryOffset = 0; | |||||
m_entryOffset = 0; | |||||
// REVIEW How do we resolve this discrepancy?! | // REVIEW How do we resolve this discrepancy?! | ||||
this.entrySize = (int)this.currEntry.getSize(); | |||||
m_entrySize = (int)m_currEntry.getSize(); | |||||
} | } | ||||
if( this.currEntry != null && this.currEntry.isGNULongNameEntry() ) | |||||
if( null != m_currEntry && m_currEntry.isGNULongNameEntry() ) | |||||
{ | { | ||||
// read in the name | // read in the name | ||||
StringBuffer longName = new StringBuffer(); | |||||
byte[] buffer = new byte[ 256 ]; | |||||
final StringBuffer longName = new StringBuffer(); | |||||
final byte[] buffer = new byte[ 256 ]; | |||||
int length = 0; | int length = 0; | ||||
while( ( length = read( buffer ) ) >= 0 ) | while( ( length = read( buffer ) ) >= 0 ) | ||||
{ | { | ||||
longName.append( new String( buffer, 0, length ) ); | |||||
final String str = new String( buffer, 0, length ); | |||||
longName.append( str ); | |||||
} | } | ||||
getNextEntry(); | getNextEntry(); | ||||
this.currEntry.setName( longName.toString() ); | |||||
m_currEntry.setName( longName.toString() ); | |||||
} | } | ||||
return this.currEntry; | |||||
return m_currEntry; | |||||
} | } | ||||
/** | /** | ||||
@@ -201,7 +194,7 @@ public class TarInputStream extends FilterInputStream | |||||
*/ | */ | ||||
public int getRecordSize() | public int getRecordSize() | ||||
{ | { | ||||
return this.buffer.getRecordSize(); | |||||
return m_buffer.getRecordSize(); | |||||
} | } | ||||
/** | /** | ||||
@@ -217,18 +210,16 @@ public class TarInputStream extends FilterInputStream | |||||
public int available() | public int available() | ||||
throws IOException | throws IOException | ||||
{ | { | ||||
return this.entrySize - this.entryOffset; | |||||
return m_entrySize - m_entryOffset; | |||||
} | } | ||||
/** | /** | ||||
* Closes this stream. Calls the TarBuffer's close() method. | * Closes this stream. Calls the TarBuffer's close() method. | ||||
* | |||||
* @exception IOException Description of Exception | |||||
*/ | */ | ||||
public void close() | public void close() | ||||
throws IOException | throws IOException | ||||
{ | { | ||||
this.buffer.close(); | |||||
m_buffer.close(); | |||||
} | } | ||||
/** | /** | ||||
@@ -238,21 +229,19 @@ public class TarInputStream extends FilterInputStream | |||||
* @param out The OutputStream into which to write the entry's data. | * @param out The OutputStream into which to write the entry's data. | ||||
* @exception IOException Description of Exception | * @exception IOException Description of Exception | ||||
*/ | */ | ||||
public void copyEntryContents( OutputStream out ) | |||||
public void copyEntryContents( final OutputStream output ) | |||||
throws IOException | throws IOException | ||||
{ | { | ||||
byte[] buf = new byte[ 32 * 1024 ]; | |||||
final byte[] buffer = new byte[ 32 * 1024 ]; | |||||
while( true ) | while( true ) | ||||
{ | { | ||||
int numRead = this.read( buf, 0, buf.length ); | |||||
final int numRead = read( buffer, 0, buffer.length ); | |||||
if( numRead == -1 ) | if( numRead == -1 ) | ||||
{ | { | ||||
break; | break; | ||||
} | } | ||||
out.write( buf, 0, numRead ); | |||||
output.write( buffer, 0, numRead ); | |||||
} | } | ||||
} | } | ||||
@@ -285,15 +274,14 @@ public class TarInputStream extends FilterInputStream | |||||
public int read() | public int read() | ||||
throws IOException | throws IOException | ||||
{ | { | ||||
int num = this.read( this.oneBuf, 0, 1 ); | |||||
final int num = read( m_oneBuf, 0, 1 ); | |||||
if( num == -1 ) | if( num == -1 ) | ||||
{ | { | ||||
return num; | return num; | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
return (int)this.oneBuf[ 0 ]; | |||||
return (int)m_oneBuf[ 0 ]; | |||||
} | } | ||||
} | } | ||||
@@ -305,10 +293,10 @@ public class TarInputStream extends FilterInputStream | |||||
* @return The number of bytes read, or -1 at EOF. | * @return The number of bytes read, or -1 at EOF. | ||||
* @exception IOException Description of Exception | * @exception IOException Description of Exception | ||||
*/ | */ | ||||
public int read( byte[] buf ) | |||||
public int read( final byte[] buffer ) | |||||
throws IOException | throws IOException | ||||
{ | { | ||||
return this.read( buf, 0, buf.length ); | |||||
return read( buffer, 0, buffer.length ); | |||||
} | } | ||||
/** | /** | ||||
@@ -318,86 +306,89 @@ public class TarInputStream extends FilterInputStream | |||||
* | * | ||||
* @param buf The buffer into which to place bytes read. | * @param buf The buffer into which to place bytes read. | ||||
* @param offset The offset at which to place bytes read. | * @param offset The offset at which to place bytes read. | ||||
* @param numToRead The number of bytes to read. | |||||
* @param count The number of bytes to read. | |||||
* @return The number of bytes read, or -1 at EOF. | * @return The number of bytes read, or -1 at EOF. | ||||
* @exception IOException Description of Exception | |||||
*/ | */ | ||||
public int read( byte[] buf, int offset, int numToRead ) | |||||
public int read( final byte[] buffer, | |||||
final int offset, | |||||
final int count ) | |||||
throws IOException | throws IOException | ||||
{ | { | ||||
int position = offset; | |||||
int numToRead = count; | |||||
int totalRead = 0; | int totalRead = 0; | ||||
if( this.entryOffset >= this.entrySize ) | |||||
if( m_entryOffset >= m_entrySize ) | |||||
{ | { | ||||
return -1; | return -1; | ||||
} | } | ||||
if( ( numToRead + this.entryOffset ) > this.entrySize ) | |||||
if( ( numToRead + m_entryOffset ) > m_entrySize ) | |||||
{ | { | ||||
numToRead = ( this.entrySize - this.entryOffset ); | |||||
numToRead = ( m_entrySize - m_entryOffset ); | |||||
} | } | ||||
if( this.readBuf != null ) | |||||
if( null != m_readBuf ) | |||||
{ | { | ||||
int sz = ( numToRead > this.readBuf.length ) ? this.readBuf.length | |||||
: numToRead; | |||||
final int size = | |||||
( numToRead > m_readBuf.length ) ? m_readBuf.length : numToRead; | |||||
System.arraycopy( this.readBuf, 0, buf, offset, sz ); | |||||
System.arraycopy( m_readBuf, 0, buffer, position, size ); | |||||
if( sz >= this.readBuf.length ) | |||||
if( size >= m_readBuf.length ) | |||||
{ | { | ||||
this.readBuf = null; | |||||
m_readBuf = null; | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
int newLen = this.readBuf.length - sz; | |||||
byte[] newBuf = new byte[ newLen ]; | |||||
final int newLength = m_readBuf.length - size; | |||||
final byte[] newBuffer = new byte[ newLength ]; | |||||
System.arraycopy( this.readBuf, sz, newBuf, 0, newLen ); | |||||
System.arraycopy( m_readBuf, size, newBuffer, 0, newLength ); | |||||
this.readBuf = newBuf; | |||||
m_readBuf = newBuffer; | |||||
} | } | ||||
totalRead += sz; | |||||
numToRead -= sz; | |||||
offset += sz; | |||||
totalRead += size; | |||||
numToRead -= size; | |||||
position += size; | |||||
} | } | ||||
while( numToRead > 0 ) | while( numToRead > 0 ) | ||||
{ | { | ||||
byte[] rec = this.buffer.readRecord(); | |||||
if( rec == null ) | |||||
final byte[] rec = m_buffer.readRecord(); | |||||
if( null == rec ) | |||||
{ | { | ||||
// Unexpected EOF! | // Unexpected EOF! | ||||
throw new IOException( "unexpected EOF with " + numToRead | |||||
+ " bytes unread" ); | |||||
final String message = | |||||
"unexpected EOF with " + numToRead + " bytes unread"; | |||||
throw new IOException( message ); | |||||
} | } | ||||
int sz = numToRead; | |||||
int recLen = rec.length; | |||||
int size = numToRead; | |||||
final int recordLength = rec.length; | |||||
if( recLen > sz ) | |||||
if( recordLength > size ) | |||||
{ | { | ||||
System.arraycopy( rec, 0, buf, offset, sz ); | |||||
System.arraycopy( rec, 0, buffer, position, size ); | |||||
this.readBuf = new byte[ recLen - sz ]; | |||||
m_readBuf = new byte[ recordLength - size ]; | |||||
System.arraycopy( rec, sz, this.readBuf, 0, recLen - sz ); | |||||
System.arraycopy( rec, size, m_readBuf, 0, recordLength - size ); | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
sz = recLen; | |||||
size = recordLength; | |||||
System.arraycopy( rec, 0, buf, offset, recLen ); | |||||
System.arraycopy( rec, 0, buffer, position, recordLength ); | |||||
} | } | ||||
totalRead += sz; | |||||
numToRead -= sz; | |||||
offset += sz; | |||||
totalRead += size; | |||||
numToRead -= size; | |||||
position += size; | |||||
} | } | ||||
this.entryOffset += totalRead; | |||||
m_entryOffset += totalRead; | |||||
return totalRead; | return totalRead; | ||||
} | } | ||||
@@ -415,24 +406,19 @@ public class TarInputStream extends FilterInputStream | |||||
* entry's data if the number to skip extends beyond that point. | * entry's data if the number to skip extends beyond that point. | ||||
* | * | ||||
* @param numToSkip The number of bytes to skip. | * @param numToSkip The number of bytes to skip. | ||||
* @exception IOException Description of Exception | |||||
*/ | */ | ||||
public void skip( int numToSkip ) | |||||
public void skip( final int numToSkip ) | |||||
throws IOException | throws IOException | ||||
{ | { | ||||
// REVIEW | // REVIEW | ||||
// This is horribly inefficient, but it ensures that we | // This is horribly inefficient, but it ensures that we | ||||
// properly skip over bytes via the TarBuffer... | // properly skip over bytes via the TarBuffer... | ||||
// | // | ||||
byte[] skipBuf = new byte[ 8 * 1024 ]; | |||||
final byte[] skipBuf = new byte[ 8 * 1024 ]; | |||||
for( int num = numToSkip; num > 0; ) | for( int num = numToSkip; num > 0; ) | ||||
{ | { | ||||
int numRead = this.read( skipBuf, 0, | |||||
( num > skipBuf.length ? skipBuf.length | |||||
: num ) ); | |||||
final int count = ( num > skipBuf.length ) ? skipBuf.length : num; | |||||
final int numRead = read( skipBuf, 0, count ); | |||||
if( numRead == -1 ) | if( numRead == -1 ) | ||||
{ | { | ||||
break; | break; | ||||
@@ -441,4 +427,12 @@ public class TarInputStream extends FilterInputStream | |||||
num -= numRead; | num -= numRead; | ||||
} | } | ||||
} | } | ||||
protected void debug( final String message ) | |||||
{ | |||||
if( m_debug ) | |||||
{ | |||||
System.err.println( message ); | |||||
} | |||||
} | |||||
} | } |
@@ -17,43 +17,48 @@ import java.io.OutputStream; | |||||
* stream using write(). | * stream using write(). | ||||
* | * | ||||
* @author Timothy Gerard Endres <a href="mailto:time@ice.com">time@ice.com</a> | * @author Timothy Gerard Endres <a href="mailto:time@ice.com">time@ice.com</a> | ||||
* @author <a href="mailto:peter@apache.org">Peter Donald</a> | |||||
*/ | */ | ||||
public class TarOutputStream extends FilterOutputStream | |||||
public class TarOutputStream | |||||
extends FilterOutputStream | |||||
{ | { | ||||
public final static int LONGFILE_ERROR = 0; | public final static int LONGFILE_ERROR = 0; | ||||
public final static int LONGFILE_TRUNCATE = 1; | public final static int LONGFILE_TRUNCATE = 1; | ||||
public final static int LONGFILE_GNU = 2; | public final static int LONGFILE_GNU = 2; | ||||
protected int longFileMode = LONGFILE_ERROR; | |||||
protected byte[] assemBuf; | |||||
protected int assemLen; | |||||
protected TarBuffer buffer; | |||||
protected int currBytes; | |||||
protected int currSize; | |||||
protected boolean debug; | |||||
protected byte[] oneBuf; | |||||
protected byte[] recordBuf; | |||||
public TarOutputStream( OutputStream os ) | |||||
private int m_longFileMode = LONGFILE_ERROR; | |||||
private byte[] m_assemBuf; | |||||
private int m_assemLen; | |||||
private TarBuffer m_buffer; | |||||
private int m_currBytes; | |||||
private int m_currSize; | |||||
private boolean m_debug; | |||||
private byte[] m_oneBuf; | |||||
private byte[] m_recordBuf; | |||||
public TarOutputStream( final OutputStream output ) | |||||
{ | { | ||||
this( os, TarBuffer.DEFAULT_BLKSIZE, TarBuffer.DEFAULT_RCDSIZE ); | |||||
this( output, TarBuffer.DEFAULT_BLKSIZE, TarBuffer.DEFAULT_RCDSIZE ); | |||||
} | } | ||||
public TarOutputStream( OutputStream os, int blockSize ) | |||||
public TarOutputStream( final OutputStream output, final int blockSize ) | |||||
{ | { | ||||
this( os, blockSize, TarBuffer.DEFAULT_RCDSIZE ); | |||||
this( output, blockSize, TarBuffer.DEFAULT_RCDSIZE ); | |||||
} | } | ||||
public TarOutputStream( OutputStream os, int blockSize, int recordSize ) | |||||
public TarOutputStream( final OutputStream output, | |||||
final int blockSize, | |||||
final int recordSize ) | |||||
{ | { | ||||
super( os ); | |||||
this.buffer = new TarBuffer( os, blockSize, recordSize ); | |||||
this.debug = false; | |||||
this.assemLen = 0; | |||||
this.assemBuf = new byte[ recordSize ]; | |||||
this.recordBuf = new byte[ recordSize ]; | |||||
this.oneBuf = new byte[ 1 ]; | |||||
super( output ); | |||||
m_buffer = new TarBuffer( output, blockSize, recordSize ); | |||||
m_debug = false; | |||||
m_assemLen = 0; | |||||
m_assemBuf = new byte[ recordSize ]; | |||||
m_recordBuf = new byte[ recordSize ]; | |||||
m_oneBuf = new byte[ 1 ]; | |||||
} | } | ||||
/** | /** | ||||
@@ -63,7 +68,7 @@ public class TarOutputStream extends FilterOutputStream | |||||
*/ | */ | ||||
public void setBufferDebug( boolean debug ) | public void setBufferDebug( boolean debug ) | ||||
{ | { | ||||
this.buffer.setDebug( debug ); | |||||
m_buffer.setDebug( debug ); | |||||
} | } | ||||
/** | /** | ||||
@@ -71,14 +76,14 @@ public class TarOutputStream extends FilterOutputStream | |||||
* | * | ||||
* @param debugF True to turn on debugging. | * @param debugF True to turn on debugging. | ||||
*/ | */ | ||||
public void setDebug( boolean debugF ) | |||||
public void setDebug( boolean debug ) | |||||
{ | { | ||||
this.debug = debugF; | |||||
m_debug = debug; | |||||
} | } | ||||
public void setLongFileMode( int longFileMode ) | |||||
public void setLongFileMode( final int longFileMode ) | |||||
{ | { | ||||
this.longFileMode = longFileMode; | |||||
m_longFileMode = longFileMode; | |||||
} | } | ||||
/** | /** | ||||
@@ -88,7 +93,7 @@ public class TarOutputStream extends FilterOutputStream | |||||
*/ | */ | ||||
public int getRecordSize() | public int getRecordSize() | ||||
{ | { | ||||
return this.buffer.getRecordSize(); | |||||
return m_buffer.getRecordSize(); | |||||
} | } | ||||
/** | /** | ||||
@@ -100,8 +105,8 @@ public class TarOutputStream extends FilterOutputStream | |||||
public void close() | public void close() | ||||
throws IOException | throws IOException | ||||
{ | { | ||||
this.finish(); | |||||
this.buffer.close(); | |||||
finish(); | |||||
m_buffer.close(); | |||||
} | } | ||||
/** | /** | ||||
@@ -116,24 +121,25 @@ public class TarOutputStream extends FilterOutputStream | |||||
public void closeEntry() | public void closeEntry() | ||||
throws IOException | throws IOException | ||||
{ | { | ||||
if( this.assemLen > 0 ) | |||||
if( m_assemLen > 0 ) | |||||
{ | { | ||||
for( int i = this.assemLen; i < this.assemBuf.length; ++i ) | |||||
for( int i = m_assemLen; i < m_assemBuf.length; ++i ) | |||||
{ | { | ||||
this.assemBuf[ i ] = 0; | |||||
m_assemBuf[ i ] = 0; | |||||
} | } | ||||
this.buffer.writeRecord( this.assemBuf ); | |||||
m_buffer.writeRecord( m_assemBuf ); | |||||
this.currBytes += this.assemLen; | |||||
this.assemLen = 0; | |||||
m_currBytes += m_assemLen; | |||||
m_assemLen = 0; | |||||
} | } | ||||
if( this.currBytes < this.currSize ) | |||||
if( m_currBytes < m_currSize ) | |||||
{ | { | ||||
throw new IOException( "entry closed at '" + this.currBytes | |||||
+ "' before the '" + this.currSize | |||||
+ "' bytes specified in the header were written" ); | |||||
final String message = "entry closed at '" + m_currBytes + | |||||
"' before the '" + m_currSize + | |||||
"' bytes specified in the header were written"; | |||||
throw new IOException( message ); | |||||
} | } | ||||
} | } | ||||
@@ -146,7 +152,7 @@ public class TarOutputStream extends FilterOutputStream | |||||
public void finish() | public void finish() | ||||
throws IOException | throws IOException | ||||
{ | { | ||||
this.writeEOFRecord(); | |||||
writeEOFRecord(); | |||||
} | } | ||||
/** | /** | ||||
@@ -160,18 +166,19 @@ public class TarOutputStream extends FilterOutputStream | |||||
* @param entry The TarEntry to be written to the archive. | * @param entry The TarEntry to be written to the archive. | ||||
* @exception IOException Description of Exception | * @exception IOException Description of Exception | ||||
*/ | */ | ||||
public void putNextEntry( TarEntry entry ) | |||||
public void putNextEntry( final TarEntry entry ) | |||||
throws IOException | throws IOException | ||||
{ | { | ||||
if( entry.getName().length() >= TarConstants.NAMELEN ) | |||||
if( entry.getName().length() >= TarEntry.NAMELEN ) | |||||
{ | { | ||||
if( longFileMode == LONGFILE_GNU ) | |||||
if( m_longFileMode == LONGFILE_GNU ) | |||||
{ | { | ||||
// create a TarEntry for the LongLink, the contents | // create a TarEntry for the LongLink, the contents | ||||
// of which are the entry's name | // of which are the entry's name | ||||
TarEntry longLinkEntry = new TarEntry( TarConstants.GNU_LONGLINK, | |||||
TarConstants.LF_GNUTYPE_LONGNAME ); | |||||
final TarEntry longLinkEntry = | |||||
new TarEntry( TarConstants.GNU_LONGLINK, | |||||
TarConstants.LF_GNUTYPE_LONGNAME ); | |||||
longLinkEntry.setSize( entry.getName().length() + 1 ); | longLinkEntry.setSize( entry.getName().length() + 1 ); | ||||
putNextEntry( longLinkEntry ); | putNextEntry( longLinkEntry ); | ||||
@@ -179,26 +186,26 @@ public class TarOutputStream extends FilterOutputStream | |||||
write( 0 ); | write( 0 ); | ||||
closeEntry(); | closeEntry(); | ||||
} | } | ||||
else if( longFileMode != LONGFILE_TRUNCATE ) | |||||
else if( m_longFileMode != LONGFILE_TRUNCATE ) | |||||
{ | { | ||||
throw new RuntimeException( "file name '" + entry.getName() | |||||
+ "' is too long ( > " | |||||
+ TarConstants.NAMELEN + " bytes)" ); | |||||
final String message = "file name '" + entry.getName() + | |||||
"' is too long ( > " + TarEntry.NAMELEN + " bytes)"; | |||||
throw new IOException( message ); | |||||
} | } | ||||
} | } | ||||
entry.writeEntryHeader( this.recordBuf ); | |||||
this.buffer.writeRecord( this.recordBuf ); | |||||
entry.writeEntryHeader( m_recordBuf ); | |||||
m_buffer.writeRecord( m_recordBuf ); | |||||
this.currBytes = 0; | |||||
m_currBytes = 0; | |||||
if( entry.isDirectory() ) | if( entry.isDirectory() ) | ||||
{ | { | ||||
this.currSize = 0; | |||||
m_currSize = 0; | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
this.currSize = (int)entry.getSize(); | |||||
m_currSize = (int)entry.getSize(); | |||||
} | } | ||||
} | } | ||||
@@ -206,15 +213,15 @@ public class TarOutputStream extends FilterOutputStream | |||||
* Writes a byte to the current tar archive entry. This method simply calls | * Writes a byte to the current tar archive entry. This method simply calls | ||||
* read( byte[], int, int ). | * read( byte[], int, int ). | ||||
* | * | ||||
* @param b The byte written. | |||||
* @param data The byte written. | |||||
* @exception IOException Description of Exception | * @exception IOException Description of Exception | ||||
*/ | */ | ||||
public void write( int b ) | |||||
public void write( final int data ) | |||||
throws IOException | throws IOException | ||||
{ | { | ||||
this.oneBuf[ 0 ] = (byte)b; | |||||
m_oneBuf[ 0 ] = (byte)data; | |||||
this.write( this.oneBuf, 0, 1 ); | |||||
write( m_oneBuf, 0, 1 ); | |||||
} | } | ||||
/** | /** | ||||
@@ -222,12 +229,11 @@ public class TarOutputStream extends FilterOutputStream | |||||
* write( byte[], int, int ). | * write( byte[], int, int ). | ||||
* | * | ||||
* @param wBuf The buffer to write to the archive. | * @param wBuf The buffer to write to the archive. | ||||
* @exception IOException Description of Exception | |||||
*/ | */ | ||||
public void write( byte[] wBuf ) | |||||
public void write( final byte[] buffer ) | |||||
throws IOException | throws IOException | ||||
{ | { | ||||
this.write( wBuf, 0, wBuf.length ); | |||||
write( buffer, 0, buffer.length ); | |||||
} | } | ||||
/** | /** | ||||
@@ -238,19 +244,22 @@ public class TarOutputStream extends FilterOutputStream | |||||
* manages buffers that are not a multiple of recordsize in length, | * manages buffers that are not a multiple of recordsize in length, | ||||
* including assembling records from small buffers. | * including assembling records from small buffers. | ||||
* | * | ||||
* @param wBuf The buffer to write to the archive. | |||||
* @param wOffset The offset in the buffer from which to get bytes. | |||||
* @param numToWrite The number of bytes to write. | |||||
* @exception IOException Description of Exception | |||||
* @param buffer The buffer to write to the archive. | |||||
* @param offset The offset in the buffer from which to get bytes. | |||||
* @param count The number of bytes to write. | |||||
*/ | */ | ||||
public void write( byte[] wBuf, int wOffset, int numToWrite ) | |||||
public void write( final byte[] buffer, | |||||
final int offset, | |||||
final int count ) | |||||
throws IOException | throws IOException | ||||
{ | { | ||||
if( ( this.currBytes + numToWrite ) > this.currSize ) | |||||
int position = offset; | |||||
int numToWrite = count; | |||||
if( ( m_currBytes + numToWrite ) > m_currSize ) | |||||
{ | { | ||||
throw new IOException( "request to write '" + numToWrite | |||||
+ "' bytes exceeds size in header of '" | |||||
+ this.currSize + "' bytes" ); | |||||
final String message = "request to write '" + numToWrite + | |||||
"' bytes exceeds size in header of '" + m_currSize + "' bytes"; | |||||
throw new IOException( message ); | |||||
// | // | ||||
// We have to deal with assembly!!! | // We have to deal with assembly!!! | ||||
// The programmer can be writing little 32 byte chunks for all | // The programmer can be writing little 32 byte chunks for all | ||||
@@ -260,30 +269,30 @@ public class TarOutputStream extends FilterOutputStream | |||||
// | // | ||||
} | } | ||||
if( this.assemLen > 0 ) | |||||
if( m_assemLen > 0 ) | |||||
{ | { | ||||
if( ( this.assemLen + numToWrite ) >= this.recordBuf.length ) | |||||
if( ( m_assemLen + numToWrite ) >= m_recordBuf.length ) | |||||
{ | { | ||||
int aLen = this.recordBuf.length - this.assemLen; | |||||
System.arraycopy( this.assemBuf, 0, this.recordBuf, 0, | |||||
this.assemLen ); | |||||
System.arraycopy( wBuf, wOffset, this.recordBuf, | |||||
this.assemLen, aLen ); | |||||
this.buffer.writeRecord( this.recordBuf ); | |||||
this.currBytes += this.recordBuf.length; | |||||
wOffset += aLen; | |||||
numToWrite -= aLen; | |||||
this.assemLen = 0; | |||||
final int length = m_recordBuf.length - m_assemLen; | |||||
System.arraycopy( m_assemBuf, 0, m_recordBuf, 0, | |||||
m_assemLen ); | |||||
System.arraycopy( buffer, position, m_recordBuf, | |||||
m_assemLen, length ); | |||||
m_buffer.writeRecord( m_recordBuf ); | |||||
m_currBytes += m_recordBuf.length; | |||||
position += length; | |||||
numToWrite -= length; | |||||
m_assemLen = 0; | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
System.arraycopy( wBuf, wOffset, this.assemBuf, this.assemLen, | |||||
System.arraycopy( buffer, position, m_assemBuf, m_assemLen, | |||||
numToWrite ); | numToWrite ); | ||||
wOffset += numToWrite; | |||||
this.assemLen += numToWrite; | |||||
position += numToWrite; | |||||
m_assemLen += numToWrite; | |||||
numToWrite -= numToWrite; | numToWrite -= numToWrite; | ||||
} | } | ||||
} | } | ||||
@@ -295,41 +304,38 @@ public class TarOutputStream extends FilterOutputStream | |||||
// | // | ||||
while( numToWrite > 0 ) | while( numToWrite > 0 ) | ||||
{ | { | ||||
if( numToWrite < this.recordBuf.length ) | |||||
if( numToWrite < m_recordBuf.length ) | |||||
{ | { | ||||
System.arraycopy( wBuf, wOffset, this.assemBuf, this.assemLen, | |||||
System.arraycopy( buffer, position, m_assemBuf, m_assemLen, | |||||
numToWrite ); | numToWrite ); | ||||
this.assemLen += numToWrite; | |||||
m_assemLen += numToWrite; | |||||
break; | break; | ||||
} | } | ||||
this.buffer.writeRecord( wBuf, wOffset ); | |||||
m_buffer.writeRecord( buffer, position ); | |||||
int num = this.recordBuf.length; | |||||
int num = m_recordBuf.length; | |||||
this.currBytes += num; | |||||
m_currBytes += num; | |||||
numToWrite -= num; | numToWrite -= num; | ||||
wOffset += num; | |||||
position += num; | |||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* Write an EOF (end of archive) record to the tar archive. An EOF record | * Write an EOF (end of archive) record to the tar archive. An EOF record | ||||
* consists of a record of all zeros. | * consists of a record of all zeros. | ||||
* | |||||
* @exception IOException Description of Exception | |||||
*/ | */ | ||||
private void writeEOFRecord() | private void writeEOFRecord() | ||||
throws IOException | throws IOException | ||||
{ | { | ||||
for( int i = 0; i < this.recordBuf.length; ++i ) | |||||
for( int i = 0; i < m_recordBuf.length; ++i ) | |||||
{ | { | ||||
this.recordBuf[ i ] = 0; | |||||
m_recordBuf[ i ] = 0; | |||||
} | } | ||||
this.buffer.writeRecord( this.recordBuf ); | |||||
m_buffer.writeRecord( m_recordBuf ); | |||||
} | } | ||||
} | |||||
} |