GP-0: Removing unnecessary DMG NPE check, and some cleanup

(Closes #1740)
This commit is contained in:
Ryan Kurtz
2026-06-23 05:10:22 -04:00
parent 8711646775
commit a25f23b640
4 changed files with 176 additions and 180 deletions

View File

@@ -27,7 +27,7 @@ public class GByteProvider implements Closeable {
/** /**
* Constructs a byte provider using the specified file and permissions string * Constructs a byte provider using the specified file and permissions string
* @param file the file to open for random access * @param file the file to open for random access
* @param string indicating permissions used for open * @param permissions indicating permissions used for open
* @throws FileNotFoundException if the file does not exist * @throws FileNotFoundException if the file does not exist
*/ */
public GByteProvider(File file, String permissions) throws IOException { public GByteProvider(File file, String permissions) throws IOException {

View File

@@ -31,24 +31,25 @@ public class AttributesFileParser {
private GByteProvider provider; private GByteProvider provider;
private BTreeRootNodeDescriptor root; private BTreeRootNodeDescriptor root;
public AttributesFileParser( HFSXFileSystemHandler handler, String prefix ) throws IOException { public AttributesFileParser(HFSXFileSystemHandler handler, String prefix) throws IOException {
ImplHFSXFileSystemView hfsxFileSystemView = (ImplHFSXFileSystemView) handler.getFSView(); ImplHFSXFileSystemView hfsxFileSystemView = (ImplHFSXFileSystemView) handler.getFSView();
HFSPlusVolumeHeader volumeHeader = hfsxFileSystemView.getHFSPlusVolumeHeader(); HFSPlusVolumeHeader volumeHeader = hfsxFileSystemView.getHFSPlusVolumeHeader();
HFSPlusForkData attributes = volumeHeader.getAttributesFile(); HFSPlusForkData attributes = volumeHeader.getAttributesFile();
File attributesFile = writeVolumeHeaderFile( hfsxFileSystemView, attributes, prefix + "_" + "attributesFile" ); File attributesFile =
writeVolumeHeaderFile(hfsxFileSystemView, attributes, prefix + "_" + "attributesFile");
provider = new GByteProvider( attributesFile ); provider = new GByteProvider(attributesFile);
if ( attributesFile.length() == 0 ) { if (attributesFile.length() == 0) {
return; return;
} }
GBinaryReader reader = new GBinaryReader( provider, false ); GBinaryReader reader = new GBinaryReader(provider, false);
root = new BTreeRootNodeDescriptor( reader ); root = new BTreeRootNodeDescriptor(reader);
} }
public void dispose() throws IOException { public void dispose() throws IOException {
@@ -58,9 +59,10 @@ public class AttributesFileParser {
private int getFileID(FSFile file) { private int getFileID(FSFile file) {
try { try {
HFSCommonFSFile hfsFile = (HFSCommonFSFile)file; HFSCommonFSFile hfsFile = (HFSCommonFSFile) file;
CommonHFSCatalogFile catalogFile = hfsFile.getInternalCatalogFile(); CommonHFSCatalogFile catalogFile = hfsFile.getInternalCatalogFile();
CommonHFSCatalogFile.HFSPlusImplementation hfsPlusCatalogFile = (CommonHFSCatalogFile.HFSPlusImplementation)catalogFile; CommonHFSCatalogFile.HFSPlusImplementation hfsPlusCatalogFile =
(CommonHFSCatalogFile.HFSPlusImplementation) catalogFile;
HFSPlusCatalogFile underlying = hfsPlusCatalogFile.getUnderlying(); HFSPlusCatalogFile underlying = hfsPlusCatalogFile.getUnderlying();
HFSCatalogNodeID fileID = underlying.getFileID(); HFSCatalogNodeID fileID = underlying.getFileID();
return fileID.toInt(); return fileID.toInt();
@@ -70,49 +72,42 @@ public class AttributesFileParser {
} }
} }
private File writeVolumeHeaderFile( ImplHFSXFileSystemView hfsxFileSystemView, private File writeVolumeHeaderFile(ImplHFSXFileSystemView hfsxFileSystemView,
HFSPlusForkData volumeHeaderFile, HFSPlusForkData volumeHeaderFile,
String volumeHeaderFileName ) throws IOException { String volumeHeaderFileName) throws IOException {
if (volumeHeaderFile == null) { File file = File.createTempFile("Ghidra_" + volumeHeaderFileName + "_", ".tmp");
return null;
}
File file = File.createTempFile( "Ghidra_" + volumeHeaderFileName + "_", ".tmp" );
file.deleteOnExit(); file.deleteOnExit();
OutputStream out = new FileOutputStream( file ); try (OutputStream out = new FileOutputStream(file)) {
try { CommonHFSForkData fork = CommonHFSForkData.create(volumeHeaderFile);
CommonHFSForkData fork = CommonHFSForkData.create( volumeHeaderFile ); hfsxFileSystemView.extractForkToStream(fork, fork.getBasicExtents(), out,
hfsxFileSystemView.extractForkToStream( fork, fork.getBasicExtents(), out, new NullProgressMonitor() {} ); new NullProgressMonitor() {/*empty*/});
}
finally {
out.close();
} }
return file; return file;
} }
public DecmpfsHeader getDecmpfsHeader(FSFile file) throws IOException { public DecmpfsHeader getDecmpfsHeader(FSFile file) {
if ( root == null ) { if (root == null) {
return null; return null;
} }
if ( map.get( file ) != null ) { if (map.get(file) != null) {
return map.get( file ); return map.get(file);
} }
int fileID = getFileID( file ); int fileID = getFileID(file);
if ( fileID == -1 ) { if (fileID == -1) {
return null; return null;
} }
for ( BTreeNodeDescriptor node : root.getNodes() ) { for (BTreeNodeDescriptor node : root.getNodes()) {
for ( BTreeNodeRecord record : node.getRecords() ) { for (BTreeNodeRecord record : node.getRecords()) {
if ( record.getFileID() == fileID ) { if (record.getFileID() == fileID) {
DecmpfsHeader header = record.getDecmpfsHeader(); DecmpfsHeader header = record.getDecmpfsHeader();
if ( header != null ) { if (header != null) {
map.put( file, header ); map.put(file, header);
return header; return header;
} }
} }
@@ -121,5 +116,4 @@ public class AttributesFileParser {
return null; return null;
} }
} }

View File

@@ -39,7 +39,7 @@ public class DmgFileReader implements Closeable {
private List<FSFolder> rootFolders = new ArrayList<FSFolder>(); private List<FSFolder> rootFolders = new ArrayList<FSFolder>();
private List<FileSystemHandler> fileSystemHandlers = new ArrayList<FileSystemHandler>(); private List<FileSystemHandler> fileSystemHandlers = new ArrayList<FileSystemHandler>();
public DmgFileReader( GByteProvider provider ) { public DmgFileReader(GByteProvider provider) {
this.provider = provider; this.provider = provider;
} }
@@ -85,23 +85,23 @@ public class DmgFileReader implements Closeable {
} }
} }
private void debug( byte [] plistData, String fileName ) { private void debug(byte[] plistData, String fileName) {
// TODO Auto-generated method stub // TODO Auto-generated method stub
} }
private void openPartition( Partition selectedPartition ) throws IOException { private void openPartition(Partition selectedPartition) throws IOException {
long fsOffset = selectedPartition.getStartOffset();//getPmPyPartStart()+selectedPartition.getPmLgDataStart())*blockSize; long fsOffset = selectedPartition.getStartOffset();//getPmPyPartStart()+selectedPartition.getPmLgDataStart())*blockSize;
long fsLength = selectedPartition.getLength();//getPmDataCnt()*blockSize; long fsLength = selectedPartition.getLength();//getPmDataCnt()*blockSize;
FileSystemRecognizer fsr = new FileSystemRecognizer( rras, fsOffset ); FileSystemRecognizer fsr = new FileSystemRecognizer(rras, fsOffset);
FileSystemRecognizer.FileSystemType fsType = fsr.detectFileSystem(); FileSystemRecognizer.FileSystemType fsType = fsr.detectFileSystem();
if ( fsType == FileSystemRecognizer.FileSystemType.HFS_PLUS || if (fsType == FileSystemRecognizer.FileSystemType.HFS_PLUS ||
fsType == FileSystemRecognizer.FileSystemType.HFSX || fsType == FileSystemRecognizer.FileSystemType.HFSX ||
fsType == FileSystemRecognizer.FileSystemType.HFS ) { fsType == FileSystemRecognizer.FileSystemType.HFS) {
final FileSystemMajorType fsMajorType; final FileSystemMajorType fsMajorType;
switch ( fsType ) { switch (fsType) {
case HFS: case HFS:
fsMajorType = FileSystemMajorType.APPLE_HFS; fsMajorType = FileSystemMajorType.APPLE_HFS;
break; break;
@@ -117,9 +117,9 @@ public class DmgFileReader implements Closeable {
} }
FileSystemHandlerFactory factory = fsMajorType.createDefaultHandlerFactory(); FileSystemHandlerFactory factory = fsMajorType.createDefaultHandlerFactory();
if ( factory.isSupported( StandardAttribute.CACHING_ENABLED ) ) { if (factory.isSupported(StandardAttribute.CACHING_ENABLED)) {
factory.getCreateAttributes(). factory.getCreateAttributes()
setBooleanAttribute(StandardAttribute.CACHING_ENABLED, .setBooleanAttribute(StandardAttribute.CACHING_ENABLED,
true); true);
} }
@@ -135,15 +135,18 @@ public class DmgFileReader implements Closeable {
DataLocator dataLocator = new ReadableStreamDataLocator(stage1); DataLocator dataLocator = new ReadableStreamDataLocator(stage1);
FileSystemHandler fileSystemHandler = factory.createHandler(dataLocator); FileSystemHandler fileSystemHandler = factory.createHandler(dataLocator);
fileSystemHandlers.add( fileSystemHandler ); fileSystemHandlers.add(fileSystemHandler);
rootFolders.add( fileSystemHandler.getRoot() ); rootFolders.add(fileSystemHandler.getRoot());
if ( fileSystemHandler instanceof HFSXFileSystemHandler ) { if (fileSystemHandler instanceof HFSXFileSystemHandler) {
parser = new AttributesFileParser( (HFSXFileSystemHandler)fileSystemHandler, fileSystemHandler.getRoot( ).getName( ) ); parser = new AttributesFileParser((HFSXFileSystemHandler) fileSystemHandler,
fileSystemHandler.getRoot().getName());
} }
} else { }
System.err.println("UNKNOWN file system type. Can't Open filesystem. Suspect this is an APFS.\n"); else {
System.err.println(
"UNKNOWN file system type. Can't Open filesystem. Suspect this is an APFS.\n");
} }
} }
@@ -155,7 +158,7 @@ public class DmgFileReader implements Closeable {
catch (Exception e) { catch (Exception e) {
//ignore //ignore
} }
if ( parser != null ) { if (parser != null) {
parser.dispose(); parser.dispose();
parser = null; parser = null;
} }
@@ -163,34 +166,36 @@ public class DmgFileReader implements Closeable {
rootFolders.clear(); rootFolders.clear();
} }
public InputStream getData( FSEntry entry ) throws IOException { public InputStream getData(FSEntry entry) throws IOException {
if ( entry != null && entry.isFile() ) { if (entry != null && entry.isFile()) {
FSFile fsFile = (FSFile)entry; FSFile fsFile = (FSFile) entry;
FSFork mainFork = fsFile.getMainFork(); FSFork mainFork = fsFile.getMainFork();
if ( mainFork.getLength() > 0 ) { if (mainFork.getLength() > 0) {
ReadableRandomAccessStream mainForkStream = mainFork.getReadableRandomAccessStream(); ReadableRandomAccessStream mainForkStream =
if ( mainForkStream.length() != 0 ) { mainFork.getReadableRandomAccessStream();
return new DmgInputStream( mainForkStream ); if (mainForkStream.length() != 0) {
return new DmgInputStream(mainForkStream);
} }
} }
else if ( mainFork.getLength() == 0 ) { else if (mainFork.getLength() == 0) {
FSFork resourceFork = fsFile.getForkByType( FSForkType.MACOS_RESOURCE ); FSFork resourceFork = fsFile.getForkByType(FSForkType.MACOS_RESOURCE);
ReadableRandomAccessStream resourceForkStream = resourceFork.getReadableRandomAccessStream(); ReadableRandomAccessStream resourceForkStream =
resourceFork.getReadableRandomAccessStream();
if ( parser == null ) { if (parser == null) {
return null; return null;
} }
DecmpfsHeader decmpfsHeader = parser.getDecmpfsHeader( fsFile ); DecmpfsHeader decmpfsHeader = parser.getDecmpfsHeader(fsFile);
if ( decmpfsHeader == null ) { if (decmpfsHeader == null) {
return null; return null;
} }
if ( decmpfsHeader.getCompressionType() == DecmpfsCompressionTypes.CMP_Type3 ) { if (decmpfsHeader.getCompressionType() == DecmpfsCompressionTypes.CMP_Type3) {
if ( decmpfsHeader.getAttrBytes()[ 0 ] == -1 ) { if (decmpfsHeader.getAttrBytes()[0] == -1) {
return new ByteArrayInputStream(decmpfsHeader.getAttrBytes(), 1, return new ByteArrayInputStream(decmpfsHeader.getAttrBytes(), 1,
decmpfsHeader.getAttrBytes().length - 1); decmpfsHeader.getAttrBytes().length - 1);
} }
@@ -198,7 +203,7 @@ public class DmgFileReader implements Closeable {
return new RestrictedInflaterInputStream(decmpfsHeader.getAttrBytes(), return new RestrictedInflaterInputStream(decmpfsHeader.getAttrBytes(),
(int) decmpfsHeader.getUncompressedSize()); (int) decmpfsHeader.getUncompressedSize());
} }
else if ( decmpfsHeader.getCompressionType() == DecmpfsCompressionTypes.CMP_Type4 ) { else if (decmpfsHeader.getCompressionType() == DecmpfsCompressionTypes.CMP_Type4) {
return decompressResourceFork(entry, resourceForkStream, return decompressResourceFork(entry, resourceForkStream,
(int) decmpfsHeader.getUncompressedSize()); (int) decmpfsHeader.getUncompressedSize());
} }
@@ -207,11 +212,12 @@ public class DmgFileReader implements Closeable {
return null; return null;
} }
private InputStream decompressResourceFork( FSEntry entry, private InputStream decompressResourceFork(FSEntry entry,
ReadableRandomAccessStream resourceForkStream, ReadableRandomAccessStream resourceForkStream,
int expectedLength ) throws IOException { int expectedLength) throws IOException {
File tempFile = GFileUtilityMethods.writeTemporaryFile( new DmgInputStream( resourceForkStream ) ); File tempFile =
GFileUtilityMethods.writeTemporaryFile(new DmgInputStream(resourceForkStream));
System.err.println( System.err.println(
"dmg resource fork for " + entry.getName() + ": " + tempFile.getAbsolutePath()); "dmg resource fork for " + entry.getName() + ": " + tempFile.getAbsolutePath());
@@ -313,28 +319,28 @@ public class DmgFileReader implements Closeable {
} }
} }
public List<String> getInfo( String path ) { public List<String> getInfo(String path) {
if ( path != null ) { if (path != null) {
DmgInfoGenerator info = new DmgInfoGenerator( this, path, parser ); DmgInfoGenerator info = new DmgInfoGenerator(this, path, parser);
return info.getInformation( ); return info.getInformation();
} }
return null; return null;
} }
public List<FSEntry> getListing( String path ) { public List<FSEntry> getListing(String path) {
List<FSEntry> list = new ArrayList<FSEntry>(); List<FSEntry> list = new ArrayList<FSEntry>();
if ( path == null || path.equals( "/" ) ) { if (path == null || path.equals("/")) {
for ( FileSystemHandler handler : fileSystemHandlers ) { for (FileSystemHandler handler : fileSystemHandlers) {
list.add( handler.getRoot() ); list.add(handler.getRoot());
} }
} }
else { else {
FSEntry fileByPath = getFileByPath( path ); FSEntry fileByPath = getFileByPath(path);
if ( fileByPath != null ) { if (fileByPath != null) {
if ( fileByPath.isFolder() ) { if (fileByPath.isFolder()) {
FSEntry [] listEntries = fileByPath.asFolder().listEntries(); FSEntry[] listEntries = fileByPath.asFolder().listEntries();
for ( FSEntry entry : listEntries ) { for (FSEntry entry : listEntries) {
list.add( entry ); list.add(entry);
} }
} }
} }
@@ -343,16 +349,18 @@ public class DmgFileReader implements Closeable {
} }
/** /**
* Returns the length of the given file system entry. * {@return the length of the given file system entry}
* <p>
* If the entry is actually a directory, then -1 is returned. * If the entry is actually a directory, then -1 is returned.
*
* @param entry the file system entry
*/ */
public long getLength( FSEntry entry ) { public long getLength(FSEntry entry) {
if (entry != null && entry.isFile()) { if (entry != null && entry.isFile()) {
FSFork mainFork = entry.asFile().getMainFork(); FSFork mainFork = entry.asFile().getMainFork();
if ( mainFork.getLength() > 0 ) { if (mainFork.getLength() > 0) {
return mainFork.getLength(); return mainFork.getLength();
} }
try {
if (parser != null) { if (parser != null) {
DecmpfsHeader header = parser.getDecmpfsHeader(entry.asFile()); DecmpfsHeader header = parser.getDecmpfsHeader(entry.asFile());
if (header != null) { if (header != null) {
@@ -360,41 +368,42 @@ public class DmgFileReader implements Closeable {
} }
} }
} }
catch (IOException e) {
return 1;//TODO lookup valid length in DECMPFS
}
}
return -1; return -1;
} }
/** /**
* Convert path to string array. * {@return a path converted to a string array}
* * <p>
* For example, "/a/b/c.txt" will be converted to [ "a", "b", "c.txt" ]. * For example, "/a/b/c.txt" will be converted to [ "a", "b", "c.txt" ].
* * <p>
* Note: the "a" will be stripped because it corresponds to the file system handler. * Note: the "a" will be stripped because it corresponds to the file system handler.
*
* @param path the path
*/ */
public String [] convertPathToArrayAndStripFileSystemName( String path ) { public String[] convertPathToArrayAndStripFileSystemName(String path) {
String [] splitPath = path.split( "/" ); String[] splitPath = path.split("/");
if ( splitPath.length <= 2 ) { if (splitPath.length <= 2) {
return new String[ 0 ]; return new String[0];
} }
String [] temp = new String[ splitPath.length - 2 ]; String[] temp = new String[splitPath.length - 2];
System.arraycopy( splitPath, 2, temp, 0, splitPath.length - 2 ); System.arraycopy(splitPath, 2, temp, 0, splitPath.length - 2);
return temp; return temp;
} }
/** /**
* Returns the DMG file object for the corresponding path. * {@return the DMG file object for the corresponding path}
* <p>
* Path should contain the file system handler name. * Path should contain the file system handler name.
*
* @param path the path
*/ */
public FSEntry getFileByPath( String path ) { public FSEntry getFileByPath(String path) {
if ( path == null || path.equals( "/" ) ) {//ROOT if (path == null || path.equals("/")) {//ROOT
return null; return null;
} }
for ( FileSystemHandler handler : fileSystemHandlers ) { for (FileSystemHandler handler : fileSystemHandlers) {
FSEntry entry = handler.getEntry( convertPathToArrayAndStripFileSystemName( path ) ); FSEntry entry = handler.getEntry(convertPathToArrayAndStripFileSystemName(path));
if ( entry != null ) { if (entry != null) {
return entry; return entry;
} }
} }

View File

@@ -3,7 +3,6 @@
*/ */
package mobiledevices.dmg.reader; package mobiledevices.dmg.reader;
import java.io.IOException;
import java.text.DateFormat; import java.text.DateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -20,9 +19,7 @@ import mobiledevices.dmg.decmpfs.DecmpfsHeader;
import mobiledevices.dmg.hfsplus.AttributesFileParser; import mobiledevices.dmg.hfsplus.AttributesFileParser;
/** /**
*
* @see org.catacombae.hfsexplorer.gui.FSEntrySummaryPanel * @see org.catacombae.hfsexplorer.gui.FSEntrySummaryPanel
*
*/ */
class DmgInfoGenerator { class DmgInfoGenerator {
private DmgFileReader fileSystem; private DmgFileReader fileSystem;
@@ -60,16 +57,12 @@ class DmgInfoGenerator {
appendFileID(infoList, file); appendFileID(infoList, file);
if (parser != null) { if (parser != null) {
try {
DecmpfsHeader decmpfsHeader = parser.getDecmpfsHeader(file); DecmpfsHeader decmpfsHeader = parser.getDecmpfsHeader(file);
if (decmpfsHeader != null) { if (decmpfsHeader != null) {
infoList.add( infoList.add(
"Decmpfs Size: " + getSizeString(decmpfsHeader.getUncompressedSize())); "Decmpfs Size: " + getSizeString(decmpfsHeader.getUncompressedSize()));
} }
} }
catch (IOException e) {
}
}
} }
else if (entry instanceof FSFolder) { else if (entry instanceof FSFolder) {
FSFolder folder = (FSFolder) entry; FSFolder folder = (FSFolder) entry;
@@ -201,21 +194,21 @@ class DmgInfoGenerator {
} }
private void calculateFolderSize(FSFolder folder, ObjectContainer<Long> result) { private void calculateFolderSize(FSFolder folder, ObjectContainer<Long> result) {
for (FSEntry entry : folder.listEntries()) { for (FSEntry e : folder.listEntries()) {
if (entry instanceof FSFile) { if (e instanceof FSFile) {
Long value = result.o; Long value = result.o;
value += ((FSFile) entry).getMainFork().getLength(); value += ((FSFile) e).getMainFork().getLength();
result.o = value; result.o = value;
} }
else if (entry instanceof FSFolder) { else if (e instanceof FSFolder) {
calculateFolderSize((FSFolder) entry, result); calculateFolderSize((FSFolder) e, result);
} }
else if (entry instanceof FSLink) { else if (e instanceof FSLink) {
/* Do nothing. Symbolic link targets aren't part of the folder. */ /* Do nothing. Symbolic link targets aren't part of the folder. */
} }
else { else {
System.err.println("FSEntrySummaryPanel.calculateFolderSize():" + System.err.println("FSEntrySummaryPanel.calculateFolderSize():" +
" unexpected type " + entry.getClass()); " unexpected type " + e.getClass());
} }
} }
} }