GT-2758 - fix and normalize GFileSystem.getInfo()

Remove unnecessary boilerplate impls that returned null.
Build info string better, handle the GTree node where a sub-file system
is mounted so that both are included in the info display.
Fix missing img3 icon.
This commit is contained in:
dev747368 2019-04-17 13:51:47 -04:00
parent 4ce178c419
commit 203dacdecc
36 changed files with 290 additions and 343 deletions

View File

@ -14,7 +14,7 @@
<file_extension extension=".h" icon="images/oxygen/16x16/text-x-chdr.png" />
<file_extension extension=".html" icon="images/famfamfam_silk_icons_v013/html.png" />
<file_extension extension=".img" icon="images/famfamfam_silk_icons_v013/images.png" />
<file_extension extension=".img3" icon="images/famfamfam_silk_icons_v013/bullet-orange.png" />
<file_extension extension=".img3" icon="images/famfamfam_silk_icons_v013/bullet_orange.png" />
<file_extension extension=".index" icon="images/oxygen/16x16/bookmarks.png" />
<file_extension extension=".ipsw" icon="images/oxygen/16x16/multimedia-player-apple-ipod.png" />
<file_extension extension=".iso" icon="images/nuvola/16x16/cdimage.png" />

View File

@ -108,7 +108,7 @@ public class FileSystemIndexHelper<METADATATYPE> {
* @return {@link GFile} instance or null if no file was added to the index at that path.
*/
public GFile lookup(String path) {
String[] nameparts = path.split("/");
String[] nameparts = (path != null ? path : "").split("/");
GFile parent = lookupParent(nameparts);
if (nameparts.length == 0) {
return parent;

View File

@ -15,14 +15,14 @@
*/
package ghidra.formats.gfilesystem;
import java.io.*;
import java.util.List;
import ghidra.formats.gfilesystem.annotations.FileSystemInfo;
import ghidra.util.classfinder.ExtensionPoint;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
import java.io.*;
import java.util.List;
/**
* Interface that represents a filesystem that contains files.
* <p>
@ -155,9 +155,10 @@ public interface GFileSystem extends Closeable, ExtensionPoint {
* <p>
* @param file {@link GFile} to get info message for.
* @param monitor {@link TaskMonitor} to watch and update progress.
* @return multi-line formatted string with info about the file.
* @throws IOException if IO problem.
* @return multi-line formatted string with info about the file, or null.
*/
public String getInfo(GFile file, TaskMonitor monitor) throws IOException;
default public String getInfo(GFile file, TaskMonitor monitor) {
return null;
}
}

View File

@ -129,9 +129,6 @@ public abstract class GFileSystemBase implements GFileSystem {
@Override
abstract public List<GFile> getListing(GFile directory) throws IOException;
@Override
abstract public String getInfo(GFile file, TaskMonitor monitor) throws IOException;
/**
* Legacy implementation of {@link #getInputStream(GFile, TaskMonitor)}.
*

View File

@ -130,14 +130,19 @@ public class LocalFileSystemSub implements GFileSystem {
}
@Override
public String getInfo(GFile file, TaskMonitor monitor) throws IOException {
File localFile = getFileFromGFile(file);
StringBuffer buffer = new StringBuffer();
buffer.append("Name: " + localFile.getName() + "\n");
buffer.append("Size: " + localFile.length() + "\n");
buffer.append("Date: " + new Date(localFile.lastModified()).toString() + "\n");
return buffer.toString();
public String getInfo(GFile file, TaskMonitor monitor) {
try {
File localFile = getFileFromGFile(file);
StringBuilder buffer = new StringBuilder();
buffer.append("Name: " + localFile.getName() + "\n");
buffer.append("Size: " + localFile.length() + "\n");
buffer.append("Date: " + new Date(localFile.lastModified()).toString() + "\n");
return buffer.toString();
}
catch (IOException e) {
// fail and return null
}
return null;
}
@Override

View File

@ -472,42 +472,50 @@ class FSBActionManager {
* @param monitor {@link TaskMonitor} to monitor and update when accessing the filesystems.
*/
private void showInfoForFile(FSRL fsrl, TaskMonitor monitor) {
String title = " no title ";
String info = " no information available ";
String fileSystemName = " unknown ";
String title;
String info;
if (fsrl != null) {
info = "";
title = "Info about " + fsrl.getName();
if (fsrl instanceof FSRLRoot && ((FSRLRoot) fsrl).hasContainer()) {
fsrl = ((FSRLRoot) fsrl).getContainer();
}
try (RefdFile refdFile = FileSystemService.getInstance().getRefdFile(fsrl, monitor)) {
title = fsrl.getName();
GFileSystem fs = refdFile.fsRef.getFilesystem();
fileSystemName = fs.getDescription();
info = "FSRL: " + fsrl + "\n";
DomainFile associatedDomainFile =
ProgramMappingService.getCachedDomainFileFor(fsrl);
if (associatedDomainFile != null) {
info = info + "Project file: " + associatedDomainFile.getPathname() + "\n";
}
String nodeInfo = fs.getInfo(refdFile.file, monitor);
if (nodeInfo != null) {
info += nodeInfo;
}
}
catch (IOException | CancelledException e) {
info = "Error retrieving information: " + e.getMessage();
FSRL containerFSRL = ((FSRLRoot) fsrl).getContainer();
title = containerFSRL.getName();
info = getInfoStringFor(containerFSRL, monitor);
info += "------------------------------------\n";
}
info += getInfoStringFor(fsrl, monitor);
}
else {
title = "Missing File";
info = "Unable to retrieve information";
}
MultiLineMessageDialog.showMessageDialog(plugin.getTool().getActiveWindow(),
"Info about " + title, null, "File system: " + fileSystemName + '\n' + info,
MultiLineMessageDialog.INFORMATION_MESSAGE);
MultiLineMessageDialog.showMessageDialog(plugin.getTool().getActiveWindow(), title, null,
info, MultiLineMessageDialog.INFORMATION_MESSAGE);
}
private String getInfoStringFor(FSRL fsrl, TaskMonitor monitor) {
try (RefdFile refdFile = FileSystemService.getInstance().getRefdFile(fsrl, monitor)) {
GFileSystem fs = refdFile.fsRef.getFilesystem();
String result = "File system: " + fs.getDescription() + "\n";
result += "FSRL: " + fsrl + "\n";
DomainFile associatedDomainFile = ProgramMappingService.getCachedDomainFileFor(fsrl);
if (associatedDomainFile != null) {
result += "Project file: " + associatedDomainFile.getPathname() + "\n";
}
String nodeInfo = fs.getInfo(refdFile.file, monitor);
if (nodeInfo != null) {
result += nodeInfo;
}
return result;
}
catch (IOException | CancelledException e) {
return "Error retrieving information: " + e.getMessage() + "\n";
}
}
/**
* Shows a list of supported file system types and loaders.
*/

View File

@ -55,11 +55,6 @@ public class ApkFileSystem extends GFileSystemBase {
return new ArrayList<>();
}
@Override
public String getInfo(GFile file, TaskMonitor monitor) throws IOException {
return null;
}
@Override
protected InputStream getData(GFile file, TaskMonitor monitor)
throws IOException, CancelledException, CryptoException {

View File

@ -86,7 +86,7 @@ public class BootImageFileSystem extends GFileSystemBase {
}
@Override
public String getInfo(GFile file, TaskMonitor monitor) throws IOException {
public String getInfo(GFile file, TaskMonitor monitor) {
if (file == kernelFile) {
return "This is the actual KERNEL for the android device. You can analyze this file.";
}

View File

@ -175,9 +175,4 @@ public class DexToJarFileSystem extends GFileSystemBase {
public void close() throws IOException {
super.close();
}
@Override
public String getInfo(GFile file, TaskMonitor monitor) throws IOException {
return null;
}
}

View File

@ -146,7 +146,6 @@ public class DexToSmaliFileSystem extends GFileSystemBase {
}
}
private void storeFile(GFile file, File entry) {
if (file == null) {
return;
@ -166,11 +165,6 @@ public class DexToSmaliFileSystem extends GFileSystemBase {
map.clear();
super.close();
}
@Override
public String getInfo(GFile file, TaskMonitor monitor) throws IOException {
return null;
}
}
/* DexHeader header = new DexHeader(provider);

View File

@ -95,11 +95,6 @@ public class KernelFileSystem extends GFileSystemBase {
: Collections.emptyList();
}
@Override
public String getInfo(GFile file, TaskMonitor monitor) throws IOException {
return null;
}
@Override
protected InputStream getData(GFile file, TaskMonitor monitor)
throws IOException, CancelledException, CryptoException {

View File

@ -64,7 +64,7 @@ public class OdexFileSystem extends GFileSystemBase {
}
@Override
public String getInfo(GFile file, TaskMonitor monitor) throws IOException {
public String getInfo(GFile file, TaskMonitor monitor) {
StringBuilder builder = new StringBuilder();
builder.append("Magic: " + odexHeader.getMagic()).append("\n");
builder.append("Dex Offset: " + Integer.toHexString(odexHeader.getDexOffset())).append(

View File

@ -96,11 +96,6 @@ public class AndroidXmlFileSystem extends GFileSystemBase {
return new ByteArrayInputStream(payloadBytes);
}
@Override
public String getInfo(GFile file, TaskMonitor monitor) throws IOException {
return null;
}
@Override
public List<GFile> getListing(GFile directory) throws IOException {
List<GFile> tmp = new ArrayList<>();

View File

@ -104,7 +104,7 @@ public class CoffArchiveFileSystem implements GFileSystem {
}
@Override
public String getInfo(GFile file, TaskMonitor monitor) throws IOException {
public String getInfo(GFile file, TaskMonitor monitor) {
CoffArchiveMemberHeader entry = fsih.getMetadata(file);
return (entry == null) ? null : FSUtilities.infoMapToString(getInfoMap(entry));
}

View File

@ -55,11 +55,6 @@ public class CompLzssFileSystem extends GFileSystemBase {
return null;
}
@Override
public String getInfo(GFile file, TaskMonitor monitor) throws IOException {
return null;
}
@Override
public List<GFile> getListing(GFile directory) throws IOException {
return (directory == null || directory.equals(root)) ? Arrays.asList(decompressedFile)

View File

@ -107,9 +107,9 @@ public class CpioFileSystem extends GFileSystemBase {
}
@Override
public String getInfo(GFile file, TaskMonitor monitor) throws IOException {
public String getInfo(GFile file, TaskMonitor monitor) {
CpioArchiveEntry entry = map.get(file);
StringBuffer buffer = new StringBuffer();
StringBuilder buffer = new StringBuilder();
try {
buffer.append("Name: " + entry.getName() + "\n");
buffer.append("Checksum: " + Long.toHexString(entry.getChksum()) + "\n");
@ -126,6 +126,7 @@ public class CpioFileSystem extends GFileSystemBase {
buffer.append("Device ID: " + Long.toHexString(entry.getDevice()) + "\n");
}
catch (Exception e) {
// ignore
}
return buffer.toString();
}

View File

@ -43,221 +43,219 @@ public class Ext4FileSystem implements GFileSystem {
this.provider = provider;
}
public void mountFS( TaskMonitor monitor ) throws IOException, CancelledException {
BinaryReader reader = new BinaryReader( provider, true );
reader.setPointerIndex( 0x400 );
public void mountFS(TaskMonitor monitor) throws IOException, CancelledException {
BinaryReader reader = new BinaryReader(provider, true);
reader.setPointerIndex(0x400);
Ext4SuperBlock superBlock = new Ext4SuperBlock( reader );
Ext4SuperBlock superBlock = new Ext4SuperBlock(reader);
this.volumeName = superBlock.getVolumeName( );
this.volumeName = superBlock.getVolumeName();
this.uuid = NumericUtilities.convertBytesToString( superBlock.getS_uuid( ) );
this.uuid = NumericUtilities.convertBytesToString(superBlock.getS_uuid());
int s_log_block_size = superBlock.getS_log_block_size( );
blockSize = ( int ) Math.pow( 2, ( 10 + s_log_block_size ) );
int s_log_block_size = superBlock.getS_log_block_size();
blockSize = (int) Math.pow(2, (10 + s_log_block_size));
int groupSize = blockSize * superBlock.getS_blocks_per_group( );
int numGroups = ( int ) ( provider.length( ) / groupSize );
if ( provider.length( ) % groupSize != 0 ) {
int groupSize = blockSize * superBlock.getS_blocks_per_group();
int numGroups = (int) (provider.length() / groupSize);
if (provider.length() % groupSize != 0) {
numGroups++;
}
boolean is64Bit = ( superBlock.getS_desc_size( ) > 32 ) && ( ( superBlock.getS_feature_incompat( ) & 0x80 ) > 0 );
boolean is64Bit =
(superBlock.getS_desc_size() > 32) && ((superBlock.getS_feature_incompat() & 0x80) > 0);
int groupDescriptorOffset = blockSize;
reader.setPointerIndex( groupDescriptorOffset );
Ext4GroupDescriptor [] groupDescriptors = new Ext4GroupDescriptor [ numGroups ];
for ( int i = 0; i < numGroups; i++ ) {
monitor.checkCanceled( );
groupDescriptors[ i ] = new Ext4GroupDescriptor( reader, is64Bit );
monitor.incrementProgress( 1 );
reader.setPointerIndex(groupDescriptorOffset);
Ext4GroupDescriptor[] groupDescriptors = new Ext4GroupDescriptor[numGroups];
for (int i = 0; i < numGroups; i++) {
monitor.checkCanceled();
groupDescriptors[i] = new Ext4GroupDescriptor(reader, is64Bit);
monitor.incrementProgress(1);
}
Ext4Inode [] inodes = getInodes( reader, superBlock, groupDescriptors, is64Bit, monitor );
Ext4Inode[] inodes = getInodes(reader, superBlock, groupDescriptors, is64Bit, monitor);
int s_inodes_count = superBlock.getS_inodes_count( );
for ( int i = 0; i < s_inodes_count; i++ ) {
Ext4Inode inode = inodes[ i ];
if ( inode == null ) {
int s_inodes_count = superBlock.getS_inodes_count();
for (int i = 0; i < s_inodes_count; i++) {
Ext4Inode inode = inodes[i];
if (inode == null) {
continue;
}
if ( ( inode.getI_mode( ) & Ext4Constants.I_MODE_MASK ) == Ext4Constants.S_IFDIR ) {
processDirectory( reader, superBlock, inodes, i, null, null, monitor );
if ((inode.getI_mode() & Ext4Constants.I_MODE_MASK) == Ext4Constants.S_IFDIR) {
processDirectory(reader, superBlock, inodes, i, null, null, monitor);
}
else if ( ( inode.getI_mode( ) & Ext4Constants.I_MODE_MASK ) == Ext4Constants.S_IFREG ) {
processFile( reader, superBlock, inode, monitor );
else if ((inode.getI_mode() & Ext4Constants.I_MODE_MASK) == Ext4Constants.S_IFREG) {
processFile(reader, superBlock, inode, monitor);
}
}
}
private void processDirectory( BinaryReader reader,
Ext4SuperBlock superBlock,
Ext4Inode[] inodes,
int index,
String name,
GFile parent,
TaskMonitor monitor ) throws IOException, CancelledException {
private void processDirectory(BinaryReader reader, Ext4SuperBlock superBlock,
Ext4Inode[] inodes, int index, String name, GFile parent, TaskMonitor monitor)
throws IOException, CancelledException {
if ( name != null && ( name.equals( "." ) || name.equals( ".." ) ) ) {
if (name != null && (name.equals(".") || name.equals(".."))) {
return;
}
Ext4Inode inode = inodes[ index ];
if ( name == null && parent == null ) {
parent = fsih.getRootDir( );
Ext4Inode inode = inodes[index];
if (name == null && parent == null) {
parent = fsih.getRootDir();
}
else {
if ( parent == null ) {
parent = fsih.getRootDir( );
if (parent == null) {
parent = fsih.getRootDir();
}
parent = fsih.storeFileWithParent( name, parent, -1, true, ( inode.getI_size_high( ) << 32 ) | inode.getI_size_lo( ), new Ext4File( name, inode ) );
parent = fsih.storeFileWithParent(name, parent, -1, true,
(inode.getI_size_high() << 32) | inode.getI_size_lo(), new Ext4File(name, inode));
}
if ( ( inode.getI_flags( ) & Ext4Constants.EXT4_EXTENTS_FL ) == 0 ) {
if ((inode.getI_flags() & Ext4Constants.EXT4_EXTENTS_FL) == 0) {
return;
}
boolean isDirEntry2 = ( superBlock.getS_feature_incompat( ) & Ext4Constants.INCOMPAT_FILETYPE ) != 0;
boolean isDirEntry2 =
(superBlock.getS_feature_incompat() & Ext4Constants.INCOMPAT_FILETYPE) != 0;
// if uses extents
if ( ( inode.getI_flags( ) & Ext4Constants.EXT4_EXTENTS_FL ) != 0 ) {
Ext4IBlock i_block = inode.getI_block( );
processIBlock( reader, superBlock, inodes, parent, isDirEntry2, i_block, monitor );
if ((inode.getI_flags() & Ext4Constants.EXT4_EXTENTS_FL) != 0) {
Ext4IBlock i_block = inode.getI_block();
processIBlock(reader, superBlock, inodes, parent, isDirEntry2, i_block, monitor);
}
else {
throw new IOException( "File system fails to use extents." );
throw new IOException("File system fails to use extents.");
}
inodes[ index ] = null;
inodes[index] = null;
}
private void processIBlock( BinaryReader reader,
Ext4SuperBlock superBlock,
Ext4Inode[] inodes,
GFile parent,
boolean isDirEntry2,
Ext4IBlock i_block,
TaskMonitor monitor ) throws CancelledException, IOException {
Ext4ExtentHeader header = i_block.getHeader( );
if ( header.getEh_depth( ) == 0 ) {
short numEntries = header.getEh_entries( );
List< Ext4Extent > entries = i_block.getExtentEntries( );
for ( int i = 0; i < numEntries; i++ ) {
monitor.checkCanceled( );
Ext4Extent extent = entries.get( i );
long low = extent.getEe_start_lo( ) & 0xffffffffL;
long high = extent.getEe_start_hi( ) & 0xffffffffL;
long blockNumber = ( high << 16 ) | low;
private void processIBlock(BinaryReader reader, Ext4SuperBlock superBlock, Ext4Inode[] inodes,
GFile parent, boolean isDirEntry2, Ext4IBlock i_block, TaskMonitor monitor)
throws CancelledException, IOException {
Ext4ExtentHeader header = i_block.getHeader();
if (header.getEh_depth() == 0) {
short numEntries = header.getEh_entries();
List<Ext4Extent> entries = i_block.getExtentEntries();
for (int i = 0; i < numEntries; i++) {
monitor.checkCanceled();
Ext4Extent extent = entries.get(i);
long low = extent.getEe_start_lo() & 0xffffffffL;
long high = extent.getEe_start_hi() & 0xffffffffL;
long blockNumber = (high << 16) | low;
long offset = blockNumber * blockSize;
reader.setPointerIndex( offset );
if ( isDirEntry2 ) {
processDirEntry2( reader, superBlock, inodes, parent, monitor, extent, offset );
reader.setPointerIndex(offset);
if (isDirEntry2) {
processDirEntry2(reader, superBlock, inodes, parent, monitor, extent, offset);
}
else {
processDirEntry( reader, superBlock, inodes, parent, monitor, extent, offset );
processDirEntry(reader, superBlock, inodes, parent, monitor, extent, offset);
}
}
}
else {
//throw new IOException( "Unhandled extent tree depth > 0 for inode " + index );
short numEntries = header.getEh_entries( );
short numEntries = header.getEh_entries();
List<Ext4ExtentIdx> entries = i_block.getIndexEntries();
for ( int i = 0; i < numEntries; i++ ) {
monitor.checkCanceled( );
for (int i = 0; i < numEntries; i++) {
monitor.checkCanceled();
Ext4ExtentIdx extentIndex = entries.get( i );
Ext4ExtentIdx extentIndex = entries.get(i);
long lo = extentIndex.getEi_leaf_lo();
long hi = extentIndex.getEi_leaf_hi();
long physicalBlockOfNextLevel = ( hi << 16 ) | lo;
long physicalBlockOfNextLevel = (hi << 16) | lo;
long offset = physicalBlockOfNextLevel * blockSize;
// System.out.println( ""+physicalBlockOfNextLevel );
// System.out.println( "" );
reader.setPointerIndex( offset );
Ext4IBlock intermediateBlock = new Ext4IBlock( reader, true );
processIBlock( reader, superBlock, inodes, parent, isDirEntry2, intermediateBlock, monitor );
reader.setPointerIndex(offset);
Ext4IBlock intermediateBlock = new Ext4IBlock(reader, true);
processIBlock(reader, superBlock, inodes, parent, isDirEntry2, intermediateBlock,
monitor);
}
}
}
private void processDirEntry( BinaryReader reader,
Ext4SuperBlock superBlock,
Ext4Inode [] inodes,
GFile parent,
TaskMonitor monitor,
Ext4Extent extent,
long offset ) throws CancelledException, IOException {
private void processDirEntry(BinaryReader reader, Ext4SuperBlock superBlock, Ext4Inode[] inodes,
GFile parent, TaskMonitor monitor, Ext4Extent extent, long offset)
throws CancelledException, IOException {
while ( ( reader.getPointerIndex( ) - offset ) < ( ( long ) extent.getEe_len( ) * blockSize ) ) {
monitor.checkCanceled( );
if ( reader.peekNextInt( ) == 0 ) {
while ((reader.getPointerIndex() - offset) < ((long) extent.getEe_len() * blockSize)) {
monitor.checkCanceled();
if (reader.peekNextInt() == 0) {
return;
}
Ext4DirEntry dirEnt = new Ext4DirEntry( reader );
int childIndex = dirEnt.getInode( );
Ext4Inode child = inodes[ childIndex ];
if ( ( child.getI_mode( ) & Ext4Constants.I_MODE_MASK ) == Ext4Constants.S_IFDIR ) {
String childName = dirEnt.getName( );
long readerOffset = reader.getPointerIndex( );
processDirectory( reader, superBlock, inodes, childIndex, childName, parent, monitor );
reader.setPointerIndex( readerOffset );
Ext4DirEntry dirEnt = new Ext4DirEntry(reader);
int childIndex = dirEnt.getInode();
Ext4Inode child = inodes[childIndex];
if ((child.getI_mode() & Ext4Constants.I_MODE_MASK) == Ext4Constants.S_IFDIR) {
String childName = dirEnt.getName();
long readerOffset = reader.getPointerIndex();
processDirectory(reader, superBlock, inodes, childIndex, childName, parent,
monitor);
reader.setPointerIndex(readerOffset);
}
else if ( ( child.getI_mode( ) & Ext4Constants.I_MODE_MASK ) == Ext4Constants.S_IFREG || ( child.getI_mode( ) & Ext4Constants.I_MODE_MASK ) == Ext4Constants.S_IFLNK ) {
storeFile( inodes, dirEnt, parent );
else if ((child.getI_mode() & Ext4Constants.I_MODE_MASK) == Ext4Constants.S_IFREG ||
(child.getI_mode() & Ext4Constants.I_MODE_MASK) == Ext4Constants.S_IFLNK) {
storeFile(inodes, dirEnt, parent);
}
else {
throw new IOException( "Inode " + dirEnt.getInode( ) + " has unhandled file type: " + ( child.getI_mode( ) & 0xF000 ) );
throw new IOException("Inode " + dirEnt.getInode() + " has unhandled file type: " +
(child.getI_mode() & 0xF000));
}
}
}
private void processDirEntry2( BinaryReader reader,
Ext4SuperBlock superBlock,
Ext4Inode [] inodes,
GFile parent,
TaskMonitor monitor,
Ext4Extent extent,
long offset ) throws CancelledException, IOException {
private void processDirEntry2(BinaryReader reader, Ext4SuperBlock superBlock,
Ext4Inode[] inodes, GFile parent, TaskMonitor monitor, Ext4Extent extent, long offset)
throws CancelledException, IOException {
while ( ( reader.getPointerIndex( ) - offset ) < ( ( long ) extent.getEe_len( ) * blockSize ) ) {
monitor.checkCanceled( );
if ( reader.peekNextInt( ) == 0 ) {
while ((reader.getPointerIndex() - offset) < ((long) extent.getEe_len() * blockSize)) {
monitor.checkCanceled();
if (reader.peekNextInt() == 0) {
return;
}
Ext4DirEntry2 dirEnt2 = new Ext4DirEntry2( reader );
if ( dirEnt2.getFile_type( ) == Ext4Constants.FILE_TYPE_DIRECTORY ) {
int childInode = dirEnt2.getInode( );
String childName = dirEnt2.getName( );
long readerOffset = reader.getPointerIndex( );
processDirectory( reader, superBlock, inodes, childInode, childName, parent, monitor );
reader.setPointerIndex( readerOffset );
Ext4DirEntry2 dirEnt2 = new Ext4DirEntry2(reader);
if (dirEnt2.getFile_type() == Ext4Constants.FILE_TYPE_DIRECTORY) {
int childInode = dirEnt2.getInode();
String childName = dirEnt2.getName();
long readerOffset = reader.getPointerIndex();
processDirectory(reader, superBlock, inodes, childInode, childName, parent,
monitor);
reader.setPointerIndex(readerOffset);
}
else if ( dirEnt2.getFile_type( ) == Ext4Constants.FILE_TYPE_REGULAR_FILE || dirEnt2.getFile_type( ) == Ext4Constants.FILE_TYPE_SYMBOLIC_LINK ) {
storeFile( inodes, dirEnt2, parent );
else if (dirEnt2.getFile_type() == Ext4Constants.FILE_TYPE_REGULAR_FILE ||
dirEnt2.getFile_type() == Ext4Constants.FILE_TYPE_SYMBOLIC_LINK) {
storeFile(inodes, dirEnt2, parent);
}
else {
throw new IOException( "Inode " + dirEnt2.getInode( ) + " has unhandled file type: " + dirEnt2.getFile_type( ) );
throw new IOException("Inode " + dirEnt2.getInode() + " has unhandled file type: " +
dirEnt2.getFile_type());
}
}
}
private void storeFile( Ext4Inode [] inodes, Ext4DirEntry dirEnt, GFile parent ) {
int fileInodeNum = dirEnt.getInode( );
Ext4Inode fileInode = inodes[ fileInodeNum ];
long fileSize = ( fileInode.getI_size_high( ) << 32 ) | fileInode.getI_size_lo( );
fsih.storeFileWithParent( dirEnt.getName( ), parent, -1, ( fileInode.getI_mode( ) & Ext4Constants.I_MODE_MASK ) == Ext4Constants.S_IFDIR, fileSize,
new Ext4File( dirEnt.getName( ), fileInode ) );
inodes[ fileInodeNum ] = null;
private void storeFile(Ext4Inode[] inodes, Ext4DirEntry dirEnt, GFile parent) {
int fileInodeNum = dirEnt.getInode();
Ext4Inode fileInode = inodes[fileInodeNum];
long fileSize = (fileInode.getI_size_high() << 32) | fileInode.getI_size_lo();
fsih.storeFileWithParent(dirEnt.getName(), parent, -1,
(fileInode.getI_mode() & Ext4Constants.I_MODE_MASK) == Ext4Constants.S_IFDIR, fileSize,
new Ext4File(dirEnt.getName(), fileInode));
inodes[fileInodeNum] = null;
}
private void storeFile( Ext4Inode [] inodes, Ext4DirEntry2 dirEnt2, GFile parent ) {
int fileInodeNum = dirEnt2.getInode( );
Ext4Inode fileInode = inodes[ fileInodeNum ];
if ( fileInode == null ) {
private void storeFile(Ext4Inode[] inodes, Ext4DirEntry2 dirEnt2, GFile parent) {
int fileInodeNum = dirEnt2.getInode();
Ext4Inode fileInode = inodes[fileInodeNum];
if (fileInode == null) {
return;//TODO
}
long fileSize = ( fileInode.getI_size_high( ) << 32 ) | fileInode.getI_size_lo( );
fsih.storeFileWithParent( dirEnt2.getName( ), parent, -1, dirEnt2.getFile_type( ) == Ext4Constants.FILE_TYPE_DIRECTORY, fileSize, new Ext4File( dirEnt2.getName( ), fileInode ) );
inodes[ fileInodeNum ] = null;
long fileSize = (fileInode.getI_size_high() << 32) | fileInode.getI_size_lo();
fsih.storeFileWithParent(dirEnt2.getName(), parent, -1,
dirEnt2.getFile_type() == Ext4Constants.FILE_TYPE_DIRECTORY, fileSize,
new Ext4File(dirEnt2.getName(), fileInode));
inodes[fileInodeNum] = null;
}
private void processFile( BinaryReader reader, Ext4SuperBlock superBlock, Ext4Inode inode, TaskMonitor monitor ) {
private void processFile(BinaryReader reader, Ext4SuperBlock superBlock, Ext4Inode inode,
TaskMonitor monitor) {
}
@ -272,7 +270,7 @@ public class Ext4FileSystem implements GFileSystem {
}
@Override
public String getInfo(GFile file, TaskMonitor monitor) throws IOException {
public String getInfo(GFile file, TaskMonitor monitor) {
Ext4File ext4File = fsih.getMetadata(file);
if (ext4File == null) {
return null;
@ -337,7 +335,7 @@ public class Ext4FileSystem implements GFileSystem {
throw new IOException("Not parent file for " + file);
}
symlinkDestPath =
FSUtilities.appendPath(file.getParentFile().getPath(), symlinkDestPath);
FSUtilities.appendPath(file.getParentFile().getPath(), symlinkDestPath);
}
file = lookup(symlinkDestPath);
@ -347,17 +345,17 @@ public class Ext4FileSystem implements GFileSystem {
}
private InputStream getInputStream(Ext4Inode inode) throws IOException {
int i_size_lo = inode.getI_size_lo( );
int i_size_high = inode.getI_size_high( );
long size = ( i_size_high << 32 ) | i_size_lo;
int i_size_lo = inode.getI_size_lo();
int i_size_high = inode.getI_size_high();
long size = (i_size_high << 32) | i_size_lo;
boolean usesExtents = ( inode.getI_flags( ) & Ext4Constants.EXT4_EXTENTS_FL ) != 0;
if ( usesExtents ) {
Ext4IBlock i_block = inode.getI_block( );
Ext4ExtentHeader header = i_block.getHeader( );
if ( header.getEh_depth( ) == 0 ) {
List< Ext4Extent > entries = i_block.getExtentEntries( );
return concatenateExtents( entries, size );
boolean usesExtents = (inode.getI_flags() & Ext4Constants.EXT4_EXTENTS_FL) != 0;
if (usesExtents) {
Ext4IBlock i_block = inode.getI_block();
Ext4ExtentHeader header = i_block.getHeader();
if (header.getEh_depth() == 0) {
List<Ext4Extent> entries = i_block.getExtentEntries();
return concatenateExtents(entries, size);
}
}
return null;
@ -369,65 +367,67 @@ public class Ext4FileSystem implements GFileSystem {
*
* TODO better memory management? currently loads entire file into memory.
*/
private InputStream concatenateExtents( List< Ext4Extent > entries, long actualSize ) throws IOException {
if ( actualSize > Integer.MAX_VALUE ) {
throw new IOException( "File is >2GB, too large to extract. Please report to Ghidra team." );
private InputStream concatenateExtents(List<Ext4Extent> entries, long actualSize)
throws IOException {
if (actualSize > Integer.MAX_VALUE) {
throw new IOException(
"File is >2GB, too large to extract. Please report to Ghidra team.");
}
ByteArrayOutputStream baos = new ByteArrayOutputStream( );
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for ( int i = 0 ; i < entries.size( ) ; ++i ) {
Ext4Extent extent = entries.get( i );
for (int i = 0; i < entries.size(); ++i) {
Ext4Extent extent = entries.get(i);
long low = extent.getEe_start_lo( ) & 0xffffffffL;
long high = extent.getEe_start_hi( ) & 0xffffffffL;
long blockNumber = ( high << 16 ) | low;
long low = extent.getEe_start_lo() & 0xffffffffL;
long high = extent.getEe_start_hi() & 0xffffffffL;
long blockNumber = (high << 16) | low;
long extentOffset = blockNumber * blockSize;
long extentSize = ( extent.getEe_len( ) & 0xffffL ) * blockSize;
long extentSize = (extent.getEe_len() & 0xffffL) * blockSize;
try {
byte [] extentBytes = provider.readBytes( extentOffset, extentSize );
baos.write( extentBytes );
byte[] extentBytes = provider.readBytes(extentOffset, extentSize);
baos.write(extentBytes);
}
catch ( IOException e ) {
catch (IOException e) {
// ignore
}
}
return new ByteArrayInputStream( baos.toByteArray( ), 0, (int) actualSize );
return new ByteArrayInputStream(baos.toByteArray(), 0, (int) actualSize);
}
private Ext4Inode [] getInodes( BinaryReader reader,
Ext4SuperBlock superBlock,
Ext4GroupDescriptor [] groupDescriptors,
boolean is64Bit,
TaskMonitor monitor ) throws IOException, CancelledException {
private Ext4Inode[] getInodes(BinaryReader reader, Ext4SuperBlock superBlock,
Ext4GroupDescriptor[] groupDescriptors, boolean is64Bit, TaskMonitor monitor)
throws IOException, CancelledException {
int inodeCount = superBlock.getS_inodes_count( );
Ext4Inode [] inodes = new Ext4Inode [ inodeCount + 1 ];
int inodeCount = superBlock.getS_inodes_count();
Ext4Inode[] inodes = new Ext4Inode[inodeCount + 1];
int inodeIndex = 1;
for ( int i = 0; i < groupDescriptors.length; i++ ) {
monitor.checkCanceled( );
long inodeTableBlockOffset = groupDescriptors[ i ].getBg_inode_table_lo( ) & 0xffffffffL;
if ( is64Bit ) {
inodeTableBlockOffset = ( groupDescriptors[ i ].getBg_inode_table_hi( ) << 32 ) | inodeTableBlockOffset;
for (int i = 0; i < groupDescriptors.length; i++) {
monitor.checkCanceled();
long inodeTableBlockOffset = groupDescriptors[i].getBg_inode_table_lo() & 0xffffffffL;
if (is64Bit) {
inodeTableBlockOffset =
(groupDescriptors[i].getBg_inode_table_hi() << 32) | inodeTableBlockOffset;
}
long offset = inodeTableBlockOffset * blockSize;
reader.setPointerIndex( offset );
int inodesPerGroup = superBlock.getS_inodes_per_group( );
monitor.setMessage( "Reading inode table " + i + " of " + ( groupDescriptors.length - 1 ) + "..." );
monitor.setMaximum( inodesPerGroup );
monitor.setProgress( 0 );
for ( int j = 0; j < inodesPerGroup; j++ ) {
monitor.checkCanceled( );
monitor.incrementProgress( 1 );
reader.setPointerIndex(offset);
int inodesPerGroup = superBlock.getS_inodes_per_group();
monitor.setMessage(
"Reading inode table " + i + " of " + (groupDescriptors.length - 1) + "...");
monitor.setMaximum(inodesPerGroup);
monitor.setProgress(0);
for (int j = 0; j < inodesPerGroup; j++) {
monitor.checkCanceled();
monitor.incrementProgress(1);
Ext4Inode inode = new Ext4Inode( reader );
offset = offset + superBlock.getS_inode_size( );
reader.setPointerIndex( offset );
Ext4Inode inode = new Ext4Inode(reader);
offset = offset + superBlock.getS_inode_size();
reader.setPointerIndex(offset);
inodes[ inodeIndex++ ] = inode; //inodes[ inodesPerGroup * i + j ] = inode;
inodes[inodeIndex++] = inode; //inodes[ inodesPerGroup * i + j ] = inode;
}
}
return inodes;

View File

@ -147,12 +147,11 @@ public class GZipFileSystem implements GFileSystem {
}
@Override
public String getInfo(GFile file, TaskMonitor monitor) throws IOException {
public String getInfo(GFile file, TaskMonitor monitor) {
if (payload.equals(file)) {
return FSUtilities.infoMapToString(getInfoMap());
}
return null;
}
public Map<String, String> getInfoMap() {

View File

@ -81,9 +81,4 @@ public class Apple8900FileSystem extends GFileSystemBase {
dataFile = GFileImpl.fromFilename(this, root, "DATA", false, header.getSizeOfData(), null);
}
@Override
public String getInfo(GFile file, TaskMonitor monitor) throws IOException {
return null;
}
}

View File

@ -15,16 +15,16 @@
*/
package ghidra.file.formats.ios.dmg;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import ghidra.formats.gfilesystem.*;
import ghidra.formats.gfilesystem.annotations.FileSystemInfo;
import ghidra.util.Msg;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.*;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
/**
* A {@link GFileSystem} that uses an external DMG server process to parse DMG files
* and presents the contents as a filesystem.
@ -200,7 +200,7 @@ public class DmgClientFileSystem implements GFileSystem {
}
@Override
public String getInfo(GFile gFile, TaskMonitor monitor) throws IOException {
public String getInfo(GFile gFile, TaskMonitor monitor) {
monitor.addCancelledListener(listener);
StringBuffer buffer = new StringBuffer();

View File

@ -111,11 +111,6 @@ public class DyldCacheFileSystem extends GFileSystemBase {
}
*/
@Override
public String getInfo(GFile file, TaskMonitor monitor) throws IOException {
return null;
}
@Override
public List<GFile> getListing(GFile directory) throws IOException {
if (directory == null || directory.equals(root)) {

View File

@ -32,8 +32,8 @@ import ghidra.util.exception.CancelledException;
import ghidra.util.exception.CryptoException;
import ghidra.util.task.TaskMonitor;
@FileSystemInfo(type = "ibootim", description = "iOS "
+ iBootImConstants.SIGNATURE, factory = GFileSystemBaseFactory.class)
@FileSystemInfo(type = "ibootim", description = "iOS " +
iBootImConstants.SIGNATURE, factory = GFileSystemBaseFactory.class)
public class iBootImFileSystem extends GFileSystemBase implements GIconProvider {
private iBootImHeader header;
@ -59,19 +59,15 @@ public class iBootImFileSystem extends GFileSystemBase implements GIconProvider
public Icon getIcon(GFile file, TaskMonitor monitor) throws IOException, CancelledException {
File cacheFile = fsService.getFile(file.getFSRL(), monitor);
try (InputStream cacheInputStream = new FileInputStream(cacheFile)) {
GImageFormat format = (header.getFormat() == iBootImConstants.FORMAT_ARGB) ? GImageFormat.RGB_ALPHA_4BYTE
: GImageFormat.GRAY_ALPHA_2BYTE;
GImage image = new GImage(header.getWidth(), header.getHeight(), format, cacheInputStream,
cacheFile.length());
GImageFormat format =
(header.getFormat() == iBootImConstants.FORMAT_ARGB) ? GImageFormat.RGB_ALPHA_4BYTE
: GImageFormat.GRAY_ALPHA_2BYTE;
GImage image = new GImage(header.getWidth(), header.getHeight(), format,
cacheInputStream, cacheFile.length());
return image.toPNG();
}
}
@Override
public String getInfo(GFile file, TaskMonitor monitor) throws IOException {
return null;
}
@Override
public List<GFile> getListing(GFile directory) throws IOException {
if (directory == null || directory.equals(root)) {

View File

@ -55,11 +55,6 @@ public class Img2FileSystem extends GFileSystemBase {
return null;
}
@Override
public String getInfo(GFile file, TaskMonitor monitor) throws IOException {
return null;
}
@Override
public List<GFile> getListing(GFile directory) throws IOException {
return (directory == null || directory.equals(root)) ? Arrays.asList(imageTypeFile)

View File

@ -57,11 +57,6 @@ public class IpswFileSystem extends GFileSystemBase {
return new ArrayList<>();
}
@Override
public String getInfo(GFile file, TaskMonitor monitor) throws IOException {
return null;
}
@Override
protected InputStream getData(GFile file, TaskMonitor monitor)
throws IOException, CancelledException, CryptoException {

View File

@ -92,7 +92,7 @@ public class CrushedPNGFileSystem extends GFileSystemBase {
}
@Override
public String getInfo(GFile file, TaskMonitor monitor) throws IOException {
public String getInfo(GFile file, TaskMonitor monitor) {
return png.toString();
}

View File

@ -118,12 +118,9 @@ public class PrelinkFileSystem extends GFileSystemBase implements GFileSystemPro
}
@Override
public String getInfo(GFile file, TaskMonitor monitor) throws IOException {
public String getInfo(GFile file, TaskMonitor monitor) {
PrelinkMap info = fileToPrelinkInfoMap.get(file);
if (info != null) {
return info.toString();
}
return null;
return (info != null) ? info.toString() : null;
}
@Override

View File

@ -160,7 +160,7 @@ public class ISO9660FileSystem extends GFileSystemBase {
}
@Override
public String getInfo(GFile file, TaskMonitor monitor) throws IOException {
public String getInfo(GFile file, TaskMonitor monitor) {
ISO9660Directory dir = fileToDirectoryMap.get(file);
if (dir != null) {
return dir.toString();

View File

@ -139,7 +139,7 @@ public class JavaClassDecompilerFileSystem implements GFileSystem {
}
@Override
public String getInfo(GFile file, TaskMonitor monitor) throws IOException {
public String getInfo(GFile file, TaskMonitor monitor) {
if (fsIndexHelper.getPayloadFile().equals(file)) {
Map<String, String> info = new HashMap<>();
info.put("Class name", className);

View File

@ -110,7 +110,7 @@ public class OmfArchiveFileSystem implements GFileSystem {
}
@Override
public String getInfo(GFile file, TaskMonitor monitor) throws IOException {
public String getInfo(GFile file, TaskMonitor monitor) {
OmfLibraryRecord.MemberHeader entry = fsih.getMetadata(file);
return (entry == null) ? null : FSUtilities.infoMapToString(getInfoMap(entry));
}

View File

@ -180,7 +180,7 @@ public class SevenZipFileSystem extends GFileSystemBase {
}
@Override
public String getInfo(GFile file, TaskMonitor monitor) throws IOException {
public String getInfo(GFile file, TaskMonitor monitor) {
ISimpleInArchiveItem entry = map.get(file);
StringBuffer buffer = new StringBuffer();
try {

View File

@ -15,15 +15,15 @@
*/
package ghidra.file.formats.sparseimage;
import java.io.*;
import java.util.*;
import ghidra.app.util.bin.ByteProvider;
import ghidra.formats.gfilesystem.*;
import ghidra.formats.gfilesystem.annotations.FileSystemInfo;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
import java.io.*;
import java.util.*;
/**
* A pseudo filesystem that contains a single file that is the decompressed contents
* of the sparse container file.
@ -101,7 +101,7 @@ public class SparseImageFileSystem implements GFileSystem {
SparseImageDecompressor sid = new SparseImageDecompressor(provider, os);
sid.decompress(monitor);
}
} , monitor);
}, monitor);
}
@Override
@ -123,7 +123,7 @@ public class SparseImageFileSystem implements GFileSystem {
}
@Override
public String getInfo(GFile file, TaskMonitor monitor) throws IOException {
public String getInfo(GFile file, TaskMonitor monitor) {
if (payload.equals(file)) {
return FSUtilities.infoMapToString(getInfoMap());
}

View File

@ -15,17 +15,17 @@
*/
package ghidra.file.formats.tar;
import ghidra.formats.gfilesystem.*;
import ghidra.formats.gfilesystem.annotations.FileSystemInfo;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
import java.io.*;
import java.util.*;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import ghidra.formats.gfilesystem.*;
import ghidra.formats.gfilesystem.annotations.FileSystemInfo;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/**
* TAR file system implementation.
* <p>
@ -169,12 +169,9 @@ public class TarFileSystem implements GFileSystem {
}
@Override
public String getInfo(GFile file, TaskMonitor monitor) throws IOException {
public String getInfo(GFile file, TaskMonitor monitor) {
TarMetadata tmd = fsih.getMetadata(file);
if (tmd == null) {
throw new IOException("Unknown file " + file);
}
return FSUtilities.infoMapToString(getInfoMap(tmd.tarArchiveEntry));
return (tmd != null) ? FSUtilities.infoMapToString(getInfoMap(tmd.tarArchiveEntry)) : null;
}
@Override

View File

@ -45,12 +45,9 @@ public class UniversalBinaryFileSystem extends GFileSystemBase {
}
@Override
public String getInfo(GFile file, TaskMonitor monitor) throws IOException {
public String getInfo(GFile file, TaskMonitor monitor) {
int index = list.indexOf(file);
if (index == -1) {
return null;
}
return header.getArchitectures().get(index).toString();
return (index != -1) ? header.getArchitectures().get(index).toString() : null;
}
@Override
@ -79,7 +76,8 @@ public class UniversalBinaryFileSystem extends GFileSystemBase {
Processor processor =
CpuTypes.getProcessor(architecture.getCpuType(), architecture.getCpuSubType());
int bitSize = CpuTypes.getProcessorBitSize(architecture.getCpuType());
String name = processor + "-" + bitSize + "-cpu0x" + Integer.toHexString(architecture.getCpuSubType());
String name = processor + "-" + bitSize + "-cpu0x" +
Integer.toHexString(architecture.getCpuSubType());
GFileImpl file =
GFileImpl.fromFilename(this, root, name, false, architecture.getSize(), null);
list.add(file);
@ -100,7 +98,8 @@ public class UniversalBinaryFileSystem extends GFileSystemBase {
FatArch architecture = architectures.get(index);
return new BoundedInputStream(provider.getInputStream(architecture.getOffset()), architecture.getSize());
return new BoundedInputStream(provider.getInputStream(architecture.getOffset()),
architecture.getSize());
}
@Override

View File

@ -98,7 +98,7 @@ public class YAFFS2FileSystem extends GFileSystemBase {
}
@Override
public String getInfo(GFile file, TaskMonitor monitor) throws IOException {
public String getInfo(GFile file, TaskMonitor monitor) {
return "YAFFS2, Yet Another Flash File System V2, commonly used for Android System and UserData images.";
}

View File

@ -117,9 +117,9 @@ public class ZipFileSystem implements GFileSystem {
}
@Override
public String getInfo(GFile file, TaskMonitor monitor) throws IOException {
public String getInfo(GFile file, TaskMonitor monitor) {
ZipEntry zipEntry = fsIndexHelper.getMetadata(file);
return FSUtilities.infoMapToString(getInfoMap(zipEntry));
return (zipEntry != null) ? FSUtilities.infoMapToString(getInfoMap(zipEntry)) : null;
}
@Override

View File

@ -30,10 +30,8 @@ import ghidra.util.task.TaskMonitor;
/**
* TODO: Provide class-level documentation that describes what this file system does.
*/
@FileSystemInfo(
type = "fstypegoeshere", // ([a-z0-9]+ only)
description = "File system description goes here",
factory = SkeletonFileSystem.MyFileSystemFactory.class)
@FileSystemInfo(type = "fstypegoeshere", // ([a-z0-9]+ only)
description = "File system description goes here", factory = SkeletonFileSystem.MyFileSystemFactory.class)
public class SkeletonFileSystem implements GFileSystem {
private final FSRLRoot fsFSRL;
@ -130,7 +128,7 @@ public class SkeletonFileSystem implements GFileSystem {
}
@Override
public String getInfo(GFile file, TaskMonitor monitor) throws IOException {
public String getInfo(GFile file, TaskMonitor monitor) {
MyMetadata metadata = fsih.getMetadata(file);
return (metadata == null) ? null : FSUtilities.infoMapToString(getInfoMap(metadata));
}