mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-26 02:15:31 +02:00
faster IArchive
This commit is contained in:
parent
7f7de54b77
commit
6940e686c7
6 changed files with 304 additions and 356 deletions
|
@ -1,3 +1,14 @@
|
|||
2003-02-26 David Inglis
|
||||
* model/org/eclipse/cdt/internal/core/model/ArchiveContainer.java
|
||||
* model/org/eclipse/cdt/internal/core/model/BinaryContainer.java
|
||||
Remove warning.
|
||||
|
||||
* model/org/eclipse/cdt/internal/core/model/parser/ElfBinaryArchive.java
|
||||
* model/org/eclipse/cdt/internal/core/model/parser/ElfBinaryFile.java
|
||||
* utils/org/eclipse/cdt/utils/elf/AR.java
|
||||
Improve IBinaryObject creation from IArchive (big speed improvment)
|
||||
|
||||
|
||||
2003-02-24 Alain Magloire
|
||||
|
||||
* model/org/eclipse/cdt/internal/core/model/Marker.java:
|
||||
|
|
|
@ -15,8 +15,7 @@ import org.eclipse.core.resources.IProject;
|
|||
public class ArchiveContainer extends Parent implements IArchiveContainer {
|
||||
|
||||
CProject cProject;
|
||||
private long modificationStamp;
|
||||
|
||||
|
||||
public ArchiveContainer (CProject cProject) {
|
||||
super (cProject, null, "lib", CElement.C_CONTAINER);
|
||||
this.cProject = cProject;
|
||||
|
|
|
@ -19,7 +19,6 @@ import org.eclipse.core.runtime.CoreException;
|
|||
public class BinaryContainer extends Parent implements IBinaryContainer {
|
||||
|
||||
CProject cProject;
|
||||
private long modificationStamp;
|
||||
|
||||
public BinaryContainer (CProject cProject) {
|
||||
this (cProject, "bin");
|
||||
|
|
|
@ -45,7 +45,7 @@ public class ElfBinaryArchive extends PlatformObject implements IBinaryArchive {
|
|||
ar = new AR(location.toOSString());
|
||||
AR.ARHeader[] headers = ar.getHeaders();
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
IBinaryObject bin = new ElfBinaryFile(file, headers[i].getObjectName());
|
||||
IBinaryObject bin = new ElfBinaryFile(file, headers[i]);
|
||||
children.add(bin);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
|
|
|
@ -4,7 +4,7 @@ package org.eclipse.cdt.internal.core.model.parser;
|
|||
* (c) Copyright IBM Corp. 2000, 2001.
|
||||
* All Rights Reserved.
|
||||
*/
|
||||
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
@ -28,25 +28,23 @@ import org.eclipse.core.runtime.PlatformObject;
|
|||
|
||||
/**
|
||||
*/
|
||||
public class ElfBinaryFile extends PlatformObject implements IBinaryFile,
|
||||
IBinaryObject, IBinaryExecutable, IBinaryShared {
|
||||
|
||||
public class ElfBinaryFile extends PlatformObject implements IBinaryFile, IBinaryObject, IBinaryExecutable, IBinaryShared {
|
||||
IFile file;
|
||||
String objectName;
|
||||
AR.ARHeader header;
|
||||
long timestamp;
|
||||
String soname;
|
||||
String[] needed;
|
||||
Sizes sizes;
|
||||
Attribute attribute;
|
||||
ArrayList symbols;
|
||||
|
||||
|
||||
public ElfBinaryFile(IFile f) throws IOException {
|
||||
this(f, null);
|
||||
}
|
||||
|
||||
public ElfBinaryFile(IFile f, String n) throws IOException {
|
||||
public ElfBinaryFile(IFile f, AR.ARHeader h) throws IOException {
|
||||
header = h;
|
||||
file = f;
|
||||
objectName = n;
|
||||
loadInformation();
|
||||
hasChanged();
|
||||
}
|
||||
|
@ -55,7 +53,7 @@ public class ElfBinaryFile extends PlatformObject implements IBinaryFile,
|
|||
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryFile#getFile()
|
||||
*/
|
||||
public IFile getFile() {
|
||||
return file;
|
||||
return file;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -155,7 +153,7 @@ public class ElfBinaryFile extends PlatformObject implements IBinaryFile,
|
|||
}
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryFile#getType()
|
||||
*/
|
||||
|
@ -164,21 +162,21 @@ public class ElfBinaryFile extends PlatformObject implements IBinaryFile,
|
|||
Attribute attr = getAttribute();
|
||||
if (attr != null) {
|
||||
switch (attribute.getType()) {
|
||||
case Attribute.ELF_TYPE_EXE:
|
||||
case Attribute.ELF_TYPE_EXE :
|
||||
type = IBinaryFile.EXECUTABLE;
|
||||
break;
|
||||
break;
|
||||
|
||||
case Attribute.ELF_TYPE_SHLIB:
|
||||
case Attribute.ELF_TYPE_SHLIB :
|
||||
type = IBinaryFile.SHARED;
|
||||
break;
|
||||
break;
|
||||
|
||||
case Attribute.ELF_TYPE_OBJ:
|
||||
case Attribute.ELF_TYPE_OBJ :
|
||||
type = IBinaryFile.OBJECT;
|
||||
break;
|
||||
|
||||
case Attribute.ELF_TYPE_CORE:
|
||||
break;
|
||||
|
||||
case Attribute.ELF_TYPE_CORE :
|
||||
type = IBinaryFile.CORE;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
|
@ -197,7 +195,7 @@ public class ElfBinaryFile extends PlatformObject implements IBinaryFile,
|
|||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
return (ISymbol[])symbols.toArray(new ISymbol[0]);
|
||||
return (ISymbol[]) symbols.toArray(new ISymbol[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -206,24 +204,10 @@ public class ElfBinaryFile extends PlatformObject implements IBinaryFile,
|
|||
public InputStream getContents() {
|
||||
InputStream stream = null;
|
||||
// Archive ?
|
||||
if (file != null && objectName != null) {
|
||||
IPath location = file.getLocation();
|
||||
if (location != null) {
|
||||
AR ar = null;
|
||||
try {
|
||||
ar = new AR(file.getLocation().toOSString());
|
||||
AR.ARHeader[] headers = ar.getHeaders();
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
if (objectName.equals(headers[i].getObjectName())) {
|
||||
stream = new ByteArrayInputStream(headers[i].getObjectData());
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
}
|
||||
if (ar != null) {
|
||||
ar.dispose();
|
||||
}
|
||||
if (file != null && header != null) {
|
||||
try {
|
||||
stream = new ByteArrayInputStream(header.getObjectData());
|
||||
} catch (IOException e) {
|
||||
}
|
||||
} else if (file != null && file.exists()) {
|
||||
try {
|
||||
|
@ -241,8 +225,8 @@ public class ElfBinaryFile extends PlatformObject implements IBinaryFile,
|
|||
* @see org.eclipse.cdt.core.model.IBinaryParser.IBinaryObject#getName()
|
||||
*/
|
||||
public String getName() {
|
||||
if (objectName != null) {
|
||||
return objectName;
|
||||
if (header != null) {
|
||||
return header.getObjectName();
|
||||
}
|
||||
if (file != null) {
|
||||
return file.getName();
|
||||
|
@ -273,7 +257,7 @@ public class ElfBinaryFile extends PlatformObject implements IBinaryFile,
|
|||
}
|
||||
return sizes;
|
||||
}
|
||||
|
||||
|
||||
boolean hasChanged() {
|
||||
long modification = file.getModificationStamp();
|
||||
boolean changed = modification != timestamp;
|
||||
|
@ -283,30 +267,8 @@ public class ElfBinaryFile extends PlatformObject implements IBinaryFile,
|
|||
|
||||
protected ElfHelper getElfHelper() throws IOException {
|
||||
// Archive ?
|
||||
if (file != null && objectName != null) {
|
||||
IPath location = file.getLocation();
|
||||
if (location != null) {
|
||||
ElfHelper helper = null;
|
||||
AR ar = null;
|
||||
try {
|
||||
ar = new AR(file.getLocation().toOSString());
|
||||
AR.ARHeader[] headers = ar.getHeaders();
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
AR.ARHeader hdr = headers[i];
|
||||
if (objectName.equals(hdr.getObjectName())) {
|
||||
helper = new ElfHelper(hdr.getElf());
|
||||
break;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (ar != null) {
|
||||
ar.dispose();
|
||||
}
|
||||
}
|
||||
if (helper != null) {
|
||||
return helper;
|
||||
}
|
||||
}
|
||||
if (header != null) {
|
||||
return new ElfHelper(header.getElf());
|
||||
} else if (file != null && file.exists()) {
|
||||
IPath path = file.getLocation();
|
||||
if (path == null) {
|
||||
|
@ -331,7 +293,7 @@ public class ElfBinaryFile extends PlatformObject implements IBinaryFile,
|
|||
symbols.trimToSize();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void loadAttributes(ElfHelper helper) throws IOException {
|
||||
Elf.Dynamic[] sharedlibs = helper.getNeeded();
|
||||
needed = new String[sharedlibs.length];
|
||||
|
@ -368,8 +330,10 @@ public class ElfBinaryFile extends PlatformObject implements IBinaryFile,
|
|||
try {
|
||||
// This can fail if we use addr2line
|
||||
// but we can safely ignore the error.
|
||||
sym.filename = array[i].getFilename();
|
||||
sym.lineno = array[i].getFuncLineNumber();
|
||||
if (header == null) {
|
||||
sym.filename = array[i].getFilename();
|
||||
sym.lineno = array[i].getFuncLineNumber();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
//e.printStackTrace();
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ import java.io.IOException;
|
|||
import java.io.RandomAccessFile;
|
||||
import java.util.Vector;
|
||||
|
||||
|
||||
/**
|
||||
* The <code>AR</code> class is used for parsing standard ELF archive (ar) files.
|
||||
*
|
||||
|
@ -21,326 +20,302 @@ import java.util.Vector;
|
|||
*/
|
||||
public class AR {
|
||||
|
||||
protected String filename;
|
||||
protected ERandomAccessFile efile;
|
||||
protected long strtbl_pos = -1;
|
||||
private ARHeader[] headers;
|
||||
protected String filename;
|
||||
protected ERandomAccessFile efile;
|
||||
protected long strtbl_pos = -1;
|
||||
private ARHeader[] headers;
|
||||
|
||||
public void dispose() {
|
||||
try {
|
||||
if (efile != null) {
|
||||
efile.close();
|
||||
efile = null;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
try
|
||||
{
|
||||
if (efile != null)
|
||||
{
|
||||
efile.close();
|
||||
efile = null;
|
||||
}
|
||||
}
|
||||
catch( IOException e )
|
||||
{}
|
||||
}
|
||||
protected void finalize() throws Throwable {
|
||||
try {
|
||||
dispose();
|
||||
} finally {
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
|
||||
protected void finalize() throws Throwable {
|
||||
try
|
||||
{
|
||||
dispose();
|
||||
}
|
||||
finally
|
||||
{
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* The <code>ARHeader</code> class is used to store the per-object file
|
||||
* archive headers. It can also create an Elf object for inspecting
|
||||
* the object file data.
|
||||
*/
|
||||
public class ARHeader {
|
||||
|
||||
/**
|
||||
* The <code>ARHeader</code> class is used to store the per-object file
|
||||
* archive headers. It can also create an Elf object for inspecting
|
||||
* the object file data.
|
||||
*/
|
||||
public class ARHeader {
|
||||
private String object_name;
|
||||
private String modification_time;
|
||||
private String uid;
|
||||
private String gid;
|
||||
private String mode;
|
||||
private long size;
|
||||
private long elf_offset;
|
||||
|
||||
private String object_name;
|
||||
private String modification_time;
|
||||
private String uid;
|
||||
private String gid;
|
||||
private String mode;
|
||||
private long size;
|
||||
private long elf_offset;
|
||||
/**
|
||||
* Remove the padding from the archive header strings.
|
||||
*/
|
||||
private String removeBlanks(String str) {
|
||||
while (str.charAt(str.length() - 1) == ' ')
|
||||
str = str.substring(0, str.length() - 1);
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the name stored in the archive's string table based
|
||||
* on the offset given.
|
||||
*
|
||||
* Maintains <code>efile</code> file location.
|
||||
*
|
||||
* @param offset
|
||||
* Offset into the string table for first character of the name.
|
||||
* @throws IOException
|
||||
* <code>offset</code> not in string table bounds.
|
||||
*/
|
||||
private String nameFromStringTable(long offset) throws IOException {
|
||||
StringBuffer name = new StringBuffer(0);
|
||||
long pos = efile.getFilePointer();
|
||||
|
||||
/**
|
||||
* Remove the padding from the archive header strings.
|
||||
*/
|
||||
private String removeBlanks( String str ) {
|
||||
while( str.charAt( str.length() - 1 ) == ' ' )
|
||||
str = str.substring( 0, str.length() - 1 );
|
||||
return str;
|
||||
}
|
||||
try {
|
||||
if (strtbl_pos != -1) {
|
||||
byte temp;
|
||||
efile.seek(strtbl_pos + offset);
|
||||
while ((temp = efile.readByte()) != '\n')
|
||||
name.append((char) temp);
|
||||
}
|
||||
} finally {
|
||||
efile.seek(pos);
|
||||
}
|
||||
|
||||
return name.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the name stored in the archive's string table based
|
||||
* on the offset given.
|
||||
*
|
||||
* Maintains <code>efile</code> file location.
|
||||
*
|
||||
* @param offset
|
||||
* Offset into the string table for first character of the name.
|
||||
* @throws IOException
|
||||
* <code>offset</code> not in string table bounds.
|
||||
*/
|
||||
private String nameFromStringTable( long offset ) throws IOException {
|
||||
StringBuffer name = new StringBuffer( 0 );
|
||||
long pos = efile.getFilePointer();
|
||||
/**
|
||||
* Creates a new archive header object.
|
||||
*
|
||||
* Assumes that efile is already at the correct location in the file.
|
||||
*
|
||||
* @throws IOException
|
||||
* There was an error processing the header data from the file.
|
||||
*/
|
||||
public ARHeader() throws IOException {
|
||||
byte[] object_name = new byte[16];
|
||||
byte[] modification_time = new byte[12];
|
||||
byte[] uid = new byte[6];
|
||||
byte[] gid = new byte[6];
|
||||
byte[] mode = new byte[8];
|
||||
byte[] size = new byte[10];
|
||||
byte[] trailer = new byte[2];
|
||||
|
||||
try
|
||||
{
|
||||
if( strtbl_pos != -1 )
|
||||
{
|
||||
byte temp;
|
||||
efile.seek( strtbl_pos + offset );
|
||||
while( ( temp = efile.readByte() ) != '\n' )
|
||||
name.append( (char)temp );
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
efile.seek( pos );
|
||||
}
|
||||
//
|
||||
// Read in the archive header data. Fixed sizes.
|
||||
//
|
||||
efile.read(object_name);
|
||||
efile.read(modification_time);
|
||||
efile.read(uid);
|
||||
efile.read(gid);
|
||||
efile.read(mode);
|
||||
efile.read(size);
|
||||
efile.read(trailer);
|
||||
|
||||
return name.toString();
|
||||
}
|
||||
//
|
||||
// Save this location so we can create the Elf object later.
|
||||
//
|
||||
elf_offset = efile.getFilePointer();
|
||||
|
||||
//
|
||||
// Convert the raw bytes into strings and numbers.
|
||||
//
|
||||
this.object_name = removeBlanks(new String(object_name));
|
||||
this.modification_time = new String(modification_time);
|
||||
this.uid = new String(uid);
|
||||
this.gid = new String(gid);
|
||||
this.mode = new String(mode);
|
||||
this.size = Long.parseLong(removeBlanks(new String(size)));
|
||||
|
||||
/**
|
||||
* Creates a new archive header object.
|
||||
*
|
||||
* Assumes that efile is already at the correct location in the file.
|
||||
*
|
||||
* @throws IOException
|
||||
* There was an error processing the header data from the file.
|
||||
*/
|
||||
public ARHeader() throws IOException {
|
||||
byte[] object_name = new byte[16];
|
||||
byte[] modification_time = new byte[12];
|
||||
byte[] uid = new byte[6];
|
||||
byte[] gid = new byte[6];
|
||||
byte[] mode = new byte[8];
|
||||
byte[] size = new byte[10];
|
||||
byte[] trailer = new byte[2];
|
||||
//
|
||||
// If the name is of the format "/<number>", get name from the
|
||||
// string table.
|
||||
//
|
||||
if (strtbl_pos != -1 && this.object_name.length() > 1 && this.object_name.charAt(0) == '/') {
|
||||
try {
|
||||
long offset = Long.parseLong(this.object_name.substring(1));
|
||||
this.object_name = nameFromStringTable(offset);
|
||||
} catch (java.lang.Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Read in the archive header data. Fixed sizes.
|
||||
//
|
||||
efile.read( object_name );
|
||||
efile.read( modification_time );
|
||||
efile.read( uid );
|
||||
efile.read( gid );
|
||||
efile.read( mode );
|
||||
efile.read( size );
|
||||
efile.read( trailer );
|
||||
//
|
||||
// Strip the trailing / from the object name.
|
||||
//
|
||||
int len = this.object_name.length();
|
||||
if (len > 2 && this.object_name.charAt(len - 1) == '/') {
|
||||
this.object_name = this.object_name.substring(0, len - 1);
|
||||
}
|
||||
|
||||
//
|
||||
// Save this location so we can create the Elf object later.
|
||||
//
|
||||
elf_offset = efile.getFilePointer();
|
||||
}
|
||||
|
||||
//
|
||||
// Convert the raw bytes into strings and numbers.
|
||||
//
|
||||
this.object_name = removeBlanks( new String( object_name ) );
|
||||
this.modification_time = new String( modification_time );
|
||||
this.uid = new String( uid );
|
||||
this.gid = new String( gid );
|
||||
this.mode = new String( mode );
|
||||
this.size = Long.parseLong( removeBlanks( new String( size ) ) );
|
||||
/** Get the name of the object file */
|
||||
public String getObjectName() {
|
||||
return object_name;
|
||||
}
|
||||
|
||||
//
|
||||
// If the name is of the format "/<number>", get name from the
|
||||
// string table.
|
||||
//
|
||||
if( strtbl_pos != -1 &&
|
||||
this.object_name.length() > 1 &&
|
||||
this.object_name.charAt( 0 ) == '/' )
|
||||
{
|
||||
try
|
||||
{
|
||||
long offset = Long.parseLong( this.object_name.substring( 1 ) );
|
||||
this.object_name = nameFromStringTable( offset );
|
||||
}
|
||||
catch( java.lang.Exception e )
|
||||
{
|
||||
}
|
||||
}
|
||||
/** Get the size of the object file . */
|
||||
public long getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public String getArchiveName() {
|
||||
return filename;
|
||||
}
|
||||
|
||||
//
|
||||
// Strip the trailing / from the object name.
|
||||
//
|
||||
int len = this.object_name.length();
|
||||
if( len > 2 && this.object_name.charAt( len - 1 ) == '/' )
|
||||
{
|
||||
this.object_name = this.object_name.substring( 0, len - 1 );
|
||||
}
|
||||
/**
|
||||
* Create an new Elf object for the object file.
|
||||
*
|
||||
* @throws IOException
|
||||
* Not a valid Elf object file.
|
||||
* @return A new Elf object.
|
||||
* @see Elf#Elf( String, long )
|
||||
*/
|
||||
public Elf getElf() throws IOException {
|
||||
return new Elf(filename, elf_offset);
|
||||
}
|
||||
|
||||
}
|
||||
public Elf getElf(boolean filter_on) throws IOException {
|
||||
return new Elf(filename, elf_offset, filter_on);
|
||||
}
|
||||
|
||||
/** Get the name of the object file */
|
||||
public String getObjectName() {
|
||||
return object_name;
|
||||
}
|
||||
public byte[] getObjectData() throws IOException {
|
||||
byte[] temp = new byte[(int) size];
|
||||
if (efile != null) {
|
||||
efile.seek(elf_offset);
|
||||
efile.read(temp);
|
||||
} else {
|
||||
efile = new ERandomAccessFile(filename, "r");
|
||||
efile.seek(elf_offset);
|
||||
efile.read(temp);
|
||||
efile.close();
|
||||
efile = null;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
|
||||
/** Get the size of the object file . */
|
||||
public long getSize() {
|
||||
return size;
|
||||
}
|
||||
/**
|
||||
* Creates a new <code>AR</code> object from the contents of
|
||||
* the given file.
|
||||
*
|
||||
* @param filename The file to process.
|
||||
* @throws IOException The file is not a valid archive.
|
||||
*/
|
||||
public AR(String filename) throws IOException {
|
||||
this.filename = filename;
|
||||
efile = new ERandomAccessFile(filename, "r");
|
||||
String hdr = efile.readLine();
|
||||
if (hdr == null || hdr.compareTo("!<arch>") != 0) {
|
||||
efile.close();
|
||||
throw new IOException("Not a valid archive file.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an new Elf object for the object file.
|
||||
*
|
||||
* @throws IOException
|
||||
* Not a valid Elf object file.
|
||||
* @return A new Elf object.
|
||||
* @see Elf#Elf( String, long )
|
||||
*/
|
||||
public Elf getElf() throws IOException {
|
||||
return new Elf( filename, elf_offset );
|
||||
}
|
||||
/** Load the headers from the file (if required). */
|
||||
private void loadHeaders() throws IOException {
|
||||
if (headers != null)
|
||||
return;
|
||||
|
||||
public Elf getElf( boolean filter_on ) throws IOException {
|
||||
return new Elf( filename, elf_offset, filter_on );
|
||||
}
|
||||
Vector v = new Vector();
|
||||
try {
|
||||
//
|
||||
// Check for EOF condition
|
||||
//
|
||||
while (efile.getFilePointer() < efile.length()) {
|
||||
ARHeader header = new ARHeader();
|
||||
String name = header.getObjectName();
|
||||
|
||||
public byte[] getObjectData() throws IOException {
|
||||
byte[] temp = new byte[(int)size];
|
||||
efile.seek( elf_offset );
|
||||
efile.read( temp );
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
long pos = efile.getFilePointer();
|
||||
|
||||
//
|
||||
// If the name starts with a / it is specical.
|
||||
//
|
||||
if (name.charAt(0) != '/')
|
||||
v.add(header);
|
||||
|
||||
/**
|
||||
* Creates a new <code>AR</code> object from the contents of
|
||||
* the given file.
|
||||
*
|
||||
* @param filename The file to process.
|
||||
* @throws IOException The file is not a valid archive.
|
||||
*/
|
||||
public AR( String filename ) throws IOException {
|
||||
this.filename = filename;
|
||||
efile = new ERandomAccessFile( filename, "r" );
|
||||
String hdr = efile.readLine();
|
||||
if( hdr == null || hdr.compareTo( "!<arch>" ) != 0 ) {
|
||||
efile.close();
|
||||
throw new IOException( "Not a valid archive file." );
|
||||
}
|
||||
}
|
||||
//
|
||||
// If the name is "//" then this is the string table section.
|
||||
//
|
||||
if (name.compareTo("//") == 0)
|
||||
strtbl_pos = pos;
|
||||
|
||||
//
|
||||
// Compute the location of the next header in the archive.
|
||||
//
|
||||
pos += header.getSize();
|
||||
if ((pos % 2) != 0)
|
||||
pos++;
|
||||
|
||||
/** Load the headers from the file (if required). */
|
||||
private void loadHeaders() throws IOException {
|
||||
if( headers != null )
|
||||
return;
|
||||
efile.seek(pos);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
}
|
||||
headers = (ARHeader[]) v.toArray(new ARHeader[0]);
|
||||
}
|
||||
|
||||
Vector v = new Vector();
|
||||
try
|
||||
{
|
||||
//
|
||||
// Check for EOF condition
|
||||
//
|
||||
while( efile.getFilePointer() < efile.length() )
|
||||
{
|
||||
ARHeader header = new ARHeader();
|
||||
String name = header.getObjectName();
|
||||
/**
|
||||
* Get an array of all the object file headers for this archive.
|
||||
*
|
||||
* @throws IOException
|
||||
* Unable to process the archive file.
|
||||
* @return An array of headers, one for each object within the archive.
|
||||
* @see ARHeader
|
||||
*/
|
||||
public ARHeader[] getHeaders() throws IOException {
|
||||
loadHeaders();
|
||||
return headers;
|
||||
}
|
||||
|
||||
long pos = efile.getFilePointer();
|
||||
private boolean stringInStrings(String str, String[] set) {
|
||||
for (int i = 0; i < set.length; i++)
|
||||
if (str.compareTo(set[i]) == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// If the name starts with a / it is specical.
|
||||
//
|
||||
if( name.charAt( 0 ) != '/' )
|
||||
v.add( header );
|
||||
public String[] extractFiles(String outdir, String[] names) throws IOException {
|
||||
Vector names_used = new Vector();
|
||||
String object_name;
|
||||
int count;
|
||||
|
||||
//
|
||||
// If the name is "//" then this is the string table section.
|
||||
//
|
||||
if( name.compareTo( "//" ) == 0 )
|
||||
strtbl_pos = pos;
|
||||
loadHeaders();
|
||||
|
||||
count = 0;
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
object_name = headers[i].getObjectName();
|
||||
if (names != null && !stringInStrings(object_name, names))
|
||||
continue;
|
||||
|
||||
//
|
||||
// Compute the location of the next header in the archive.
|
||||
//
|
||||
pos += header.getSize();
|
||||
if( ( pos % 2 ) != 0 )
|
||||
pos++;
|
||||
object_name = "" + count + "_" + object_name;
|
||||
count++;
|
||||
|
||||
efile.seek( pos );
|
||||
}
|
||||
}
|
||||
catch( IOException e )
|
||||
{
|
||||
}
|
||||
headers = (ARHeader[])v.toArray( new ARHeader[0] );
|
||||
}
|
||||
byte[] data = headers[i].getObjectData();
|
||||
File output = new File(outdir, object_name);
|
||||
names_used.add(object_name);
|
||||
|
||||
RandomAccessFile rfile = new RandomAccessFile(output, "rw");
|
||||
rfile.write(data);
|
||||
rfile.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of all the object file headers for this archive.
|
||||
*
|
||||
* @throws IOException
|
||||
* Unable to process the archive file.
|
||||
* @return An array of headers, one for each object within the archive.
|
||||
* @see ARHeader
|
||||
*/
|
||||
public ARHeader[] getHeaders() throws IOException {
|
||||
loadHeaders();
|
||||
return headers;
|
||||
}
|
||||
|
||||
|
||||
private boolean stringInStrings( String str, String[] set ) {
|
||||
for( int i=0; i<set.length; i++ )
|
||||
if( str.compareTo( set[i] ) == 0 )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public String[] extractFiles( String outdir, String[] names )
|
||||
throws IOException
|
||||
{
|
||||
Vector names_used = new Vector();
|
||||
String object_name;
|
||||
int count;
|
||||
|
||||
loadHeaders();
|
||||
|
||||
count = 0;
|
||||
for( int i=0; i<headers.length; i++ )
|
||||
{
|
||||
object_name = headers[i].getObjectName();
|
||||
if( names != null && !stringInStrings( object_name, names ) )
|
||||
continue;
|
||||
|
||||
object_name = "" + count + "_" + object_name;
|
||||
count ++;
|
||||
|
||||
byte[] data = headers[i].getObjectData();
|
||||
File output = new File( outdir, object_name );
|
||||
names_used.add( object_name );
|
||||
|
||||
RandomAccessFile rfile = new RandomAccessFile( output, "rw" );
|
||||
rfile.write( data );
|
||||
rfile.close();
|
||||
}
|
||||
|
||||
return (String[])names_used.toArray( new String[0] );
|
||||
}
|
||||
|
||||
public String[] extractFiles( String outdir ) throws IOException {
|
||||
return extractFiles( outdir, null );
|
||||
}
|
||||
return (String[]) names_used.toArray(new String[0]);
|
||||
}
|
||||
|
||||
public String[] extractFiles(String outdir) throws IOException {
|
||||
return extractFiles(outdir, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue