From a25f23b64083ed28ad15863eaddf9ce5404103c6 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Tue, 23 Jun 2026 05:10:22 -0400 Subject: [PATCH] GP-0: Removing unnecessary DMG NPE check, and some cleanup (Closes #1740) --- .../dmg/ghidra/GByteProvider.java | 10 +- .../dmg/hfsplus/AttributesFileParser.java | 88 ++++--- .../dmg/reader/DmgFileReader.java | 229 +++++++++--------- .../dmg/reader/DmgInfoGenerator.java | 29 +-- 4 files changed, 176 insertions(+), 180 deletions(-) diff --git a/GPL/DMG/src/dmg/java/mobiledevices/dmg/ghidra/GByteProvider.java b/GPL/DMG/src/dmg/java/mobiledevices/dmg/ghidra/GByteProvider.java index 8cfe4bc65a..5abe85e149 100644 --- a/GPL/DMG/src/dmg/java/mobiledevices/dmg/ghidra/GByteProvider.java +++ b/GPL/DMG/src/dmg/java/mobiledevices/dmg/ghidra/GByteProvider.java @@ -25,11 +25,11 @@ public class GByteProvider implements Closeable { } /** - * Constructs a byte provider using the specified file and permissions string - * @param file the file to open for random access - * @param string indicating permissions used for open - * @throws FileNotFoundException if the file does not exist - */ + * Constructs a byte provider using the specified file and permissions string + * @param file the file to open for random access + * @param permissions indicating permissions used for open + * @throws FileNotFoundException if the file does not exist + */ public GByteProvider(File file, String permissions) throws IOException { this.file = file; this.randomAccessFile = new GRandomAccessFile(file, permissions); diff --git a/GPL/DMG/src/dmg/java/mobiledevices/dmg/hfsplus/AttributesFileParser.java b/GPL/DMG/src/dmg/java/mobiledevices/dmg/hfsplus/AttributesFileParser.java index d6d0df0449..52f5012d86 100644 --- a/GPL/DMG/src/dmg/java/mobiledevices/dmg/hfsplus/AttributesFileParser.java +++ b/GPL/DMG/src/dmg/java/mobiledevices/dmg/hfsplus/AttributesFileParser.java @@ -31,24 +31,25 @@ public class AttributesFileParser { private GByteProvider provider; private BTreeRootNodeDescriptor root; - public AttributesFileParser( HFSXFileSystemHandler handler, String prefix ) throws IOException { + public AttributesFileParser(HFSXFileSystemHandler handler, String prefix) throws IOException { - ImplHFSXFileSystemView hfsxFileSystemView = (ImplHFSXFileSystemView) handler.getFSView(); - HFSPlusVolumeHeader volumeHeader = hfsxFileSystemView.getHFSPlusVolumeHeader(); + ImplHFSXFileSystemView hfsxFileSystemView = (ImplHFSXFileSystemView) handler.getFSView(); + 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 ) { - return; - } + if (attributesFile.length() == 0) { + 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 { @@ -58,68 +59,61 @@ public class AttributesFileParser { private int getFileID(FSFile file) { try { - HFSCommonFSFile hfsFile = (HFSCommonFSFile)file; - CommonHFSCatalogFile catalogFile = hfsFile.getInternalCatalogFile(); - CommonHFSCatalogFile.HFSPlusImplementation hfsPlusCatalogFile = (CommonHFSCatalogFile.HFSPlusImplementation)catalogFile; - HFSPlusCatalogFile underlying = hfsPlusCatalogFile.getUnderlying(); - HFSCatalogNodeID fileID = underlying.getFileID(); - return fileID.toInt(); + HFSCommonFSFile hfsFile = (HFSCommonFSFile) file; + CommonHFSCatalogFile catalogFile = hfsFile.getInternalCatalogFile(); + CommonHFSCatalogFile.HFSPlusImplementation hfsPlusCatalogFile = + (CommonHFSCatalogFile.HFSPlusImplementation) catalogFile; + HFSPlusCatalogFile underlying = hfsPlusCatalogFile.getUnderlying(); + HFSCatalogNodeID fileID = underlying.getFileID(); + return fileID.toInt(); } catch (Exception e) { return -1; } } - private File writeVolumeHeaderFile( ImplHFSXFileSystemView hfsxFileSystemView, - HFSPlusForkData volumeHeaderFile, - String volumeHeaderFileName ) throws IOException { + private File writeVolumeHeaderFile(ImplHFSXFileSystemView hfsxFileSystemView, + HFSPlusForkData volumeHeaderFile, + String volumeHeaderFileName) throws IOException { - if (volumeHeaderFile == null) { - return null; - } - - File file = File.createTempFile( "Ghidra_" + volumeHeaderFileName + "_", ".tmp" ); + File file = File.createTempFile("Ghidra_" + volumeHeaderFileName + "_", ".tmp"); file.deleteOnExit(); - OutputStream out = new FileOutputStream( file ); - try { - CommonHFSForkData fork = CommonHFSForkData.create( volumeHeaderFile ); - hfsxFileSystemView.extractForkToStream( fork, fork.getBasicExtents(), out, new NullProgressMonitor() {} ); - } - finally { - out.close(); + try (OutputStream out = new FileOutputStream(file)) { + CommonHFSForkData fork = CommonHFSForkData.create(volumeHeaderFile); + hfsxFileSystemView.extractForkToStream(fork, fork.getBasicExtents(), out, + new NullProgressMonitor() {/*empty*/}); } return file; } - - public DecmpfsHeader getDecmpfsHeader(FSFile file) throws IOException { - if ( root == null ) { + public DecmpfsHeader getDecmpfsHeader(FSFile file) { + + if (root == null) { return null; } - if ( map.get( file ) != null ) { - return map.get( file ); + if (map.get(file) != null) { + return map.get(file); } - int fileID = getFileID( file ); + int fileID = getFileID(file); - if ( fileID == -1 ) { + if (fileID == -1) { return null; } - for ( BTreeNodeDescriptor node : root.getNodes() ) { - for ( BTreeNodeRecord record : node.getRecords() ) { - if ( record.getFileID() == fileID ) { + for (BTreeNodeDescriptor node : root.getNodes()) { + for (BTreeNodeRecord record : node.getRecords()) { + if (record.getFileID() == fileID) { DecmpfsHeader header = record.getDecmpfsHeader(); - if ( header != null ) { - map.put( file, header ); + if (header != null) { + map.put(file, header); return header; } } } - } - return null; + } + return null; } - } diff --git a/GPL/DMG/src/dmg/java/mobiledevices/dmg/reader/DmgFileReader.java b/GPL/DMG/src/dmg/java/mobiledevices/dmg/reader/DmgFileReader.java index c0dc379480..dd1d869fab 100644 --- a/GPL/DMG/src/dmg/java/mobiledevices/dmg/reader/DmgFileReader.java +++ b/GPL/DMG/src/dmg/java/mobiledevices/dmg/reader/DmgFileReader.java @@ -39,7 +39,7 @@ public class DmgFileReader implements Closeable { private List rootFolders = new ArrayList(); private List fileSystemHandlers = new ArrayList(); - public DmgFileReader( GByteProvider provider ) { + public DmgFileReader(GByteProvider provider) { this.provider = provider; } @@ -85,66 +85,69 @@ public class DmgFileReader implements Closeable { } } - private void debug( byte [] plistData, String fileName ) { + private void debug(byte[] plistData, String fileName) { // TODO Auto-generated method stub } - private void openPartition( Partition selectedPartition ) throws IOException { - long fsOffset = selectedPartition.getStartOffset();//getPmPyPartStart()+selectedPartition.getPmLgDataStart())*blockSize; - long fsLength = selectedPartition.getLength();//getPmDataCnt()*blockSize; + private void openPartition(Partition selectedPartition) throws IOException { + long fsOffset = selectedPartition.getStartOffset();//getPmPyPartStart()+selectedPartition.getPmLgDataStart())*blockSize; + long fsLength = selectedPartition.getLength();//getPmDataCnt()*blockSize; - FileSystemRecognizer fsr = new FileSystemRecognizer( rras, fsOffset ); - FileSystemRecognizer.FileSystemType fsType = fsr.detectFileSystem(); + FileSystemRecognizer fsr = new FileSystemRecognizer(rras, fsOffset); + FileSystemRecognizer.FileSystemType fsType = fsr.detectFileSystem(); - if ( fsType == FileSystemRecognizer.FileSystemType.HFS_PLUS || - fsType == FileSystemRecognizer.FileSystemType.HFSX || - fsType == FileSystemRecognizer.FileSystemType.HFS ) { + if (fsType == FileSystemRecognizer.FileSystemType.HFS_PLUS || + fsType == FileSystemRecognizer.FileSystemType.HFSX || + fsType == FileSystemRecognizer.FileSystemType.HFS) { - final FileSystemMajorType fsMajorType; - switch ( fsType ) { - case HFS: - fsMajorType = FileSystemMajorType.APPLE_HFS; - break; - case HFS_PLUS: - fsMajorType = FileSystemMajorType.APPLE_HFS_PLUS; - break; - case HFSX: - fsMajorType = FileSystemMajorType.APPLE_HFSX; - break; - default: - fsMajorType = null; - break; - } + final FileSystemMajorType fsMajorType; + switch (fsType) { + case HFS: + fsMajorType = FileSystemMajorType.APPLE_HFS; + break; + case HFS_PLUS: + fsMajorType = FileSystemMajorType.APPLE_HFS_PLUS; + break; + case HFSX: + fsMajorType = FileSystemMajorType.APPLE_HFSX; + break; + default: + fsMajorType = null; + break; + } - FileSystemHandlerFactory factory = fsMajorType.createDefaultHandlerFactory(); - if ( factory.isSupported( StandardAttribute.CACHING_ENABLED ) ) { - factory.getCreateAttributes(). - setBooleanAttribute(StandardAttribute.CACHING_ENABLED, - true); - } + FileSystemHandlerFactory factory = fsMajorType.createDefaultHandlerFactory(); + if (factory.isSupported(StandardAttribute.CACHING_ENABLED)) { + factory.getCreateAttributes() + .setBooleanAttribute(StandardAttribute.CACHING_ENABLED, + true); + } - ReadableRandomAccessStream stage1; + ReadableRandomAccessStream stage1; - if (fsLength > 0) { - stage1 = new ReadableConcatenatedStream(rras, fsOffset, fsLength); - } - else { - stage1 = rras; - } + if (fsLength > 0) { + stage1 = new ReadableConcatenatedStream(rras, fsOffset, fsLength); + } + else { + stage1 = rras; + } - DataLocator dataLocator = new ReadableStreamDataLocator(stage1); + DataLocator dataLocator = new ReadableStreamDataLocator(stage1); - FileSystemHandler fileSystemHandler = factory.createHandler(dataLocator); - fileSystemHandlers.add( fileSystemHandler ); + FileSystemHandler fileSystemHandler = factory.createHandler(dataLocator); + fileSystemHandlers.add(fileSystemHandler); - rootFolders.add( fileSystemHandler.getRoot() ); + rootFolders.add(fileSystemHandler.getRoot()); - if ( fileSystemHandler instanceof HFSXFileSystemHandler ) { - 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"); - } + if (fileSystemHandler instanceof HFSXFileSystemHandler) { + 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"); + } } @Override @@ -155,7 +158,7 @@ public class DmgFileReader implements Closeable { catch (Exception e) { //ignore } - if ( parser != null ) { + if (parser != null) { parser.dispose(); parser = null; } @@ -163,34 +166,36 @@ public class DmgFileReader implements Closeable { rootFolders.clear(); } - public InputStream getData( FSEntry entry ) throws IOException { - if ( entry != null && entry.isFile() ) { - FSFile fsFile = (FSFile)entry; + public InputStream getData(FSEntry entry) throws IOException { + if (entry != null && entry.isFile()) { + FSFile fsFile = (FSFile) entry; FSFork mainFork = fsFile.getMainFork(); - if ( mainFork.getLength() > 0 ) { - ReadableRandomAccessStream mainForkStream = mainFork.getReadableRandomAccessStream(); - if ( mainForkStream.length() != 0 ) { - return new DmgInputStream( mainForkStream ); + if (mainFork.getLength() > 0) { + ReadableRandomAccessStream mainForkStream = + mainFork.getReadableRandomAccessStream(); + 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 ); - ReadableRandomAccessStream resourceForkStream = resourceFork.getReadableRandomAccessStream(); + FSFork resourceFork = fsFile.getForkByType(FSForkType.MACOS_RESOURCE); + ReadableRandomAccessStream resourceForkStream = + resourceFork.getReadableRandomAccessStream(); - if ( parser == null ) { + if (parser == null) { return null; } - DecmpfsHeader decmpfsHeader = parser.getDecmpfsHeader( fsFile ); + DecmpfsHeader decmpfsHeader = parser.getDecmpfsHeader(fsFile); - if ( decmpfsHeader == null ) { + if (decmpfsHeader == 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, decmpfsHeader.getAttrBytes().length - 1); } @@ -198,7 +203,7 @@ public class DmgFileReader implements Closeable { return new RestrictedInflaterInputStream(decmpfsHeader.getAttrBytes(), (int) decmpfsHeader.getUncompressedSize()); } - else if ( decmpfsHeader.getCompressionType() == DecmpfsCompressionTypes.CMP_Type4 ) { + else if (decmpfsHeader.getCompressionType() == DecmpfsCompressionTypes.CMP_Type4) { return decompressResourceFork(entry, resourceForkStream, (int) decmpfsHeader.getUncompressedSize()); } @@ -207,11 +212,12 @@ public class DmgFileReader implements Closeable { return null; } - private InputStream decompressResourceFork( FSEntry entry, - ReadableRandomAccessStream resourceForkStream, - int expectedLength ) throws IOException { + private InputStream decompressResourceFork(FSEntry entry, + ReadableRandomAccessStream resourceForkStream, + int expectedLength) throws IOException { - File tempFile = GFileUtilityMethods.writeTemporaryFile( new DmgInputStream( resourceForkStream ) ); + File tempFile = + GFileUtilityMethods.writeTemporaryFile(new DmgInputStream(resourceForkStream)); System.err.println( "dmg resource fork for " + entry.getName() + ": " + tempFile.getAbsolutePath()); @@ -313,28 +319,28 @@ public class DmgFileReader implements Closeable { } } - public List getInfo( String path ) { - if ( path != null ) { - DmgInfoGenerator info = new DmgInfoGenerator( this, path, parser ); - return info.getInformation( ); + public List getInfo(String path) { + if (path != null) { + DmgInfoGenerator info = new DmgInfoGenerator(this, path, parser); + return info.getInformation(); } return null; } - public List getListing( String path ) { + public List getListing(String path) { List list = new ArrayList(); - if ( path == null || path.equals( "/" ) ) { - for ( FileSystemHandler handler : fileSystemHandlers ) { - list.add( handler.getRoot() ); + if (path == null || path.equals("/")) { + for (FileSystemHandler handler : fileSystemHandlers) { + list.add(handler.getRoot()); } } else { - FSEntry fileByPath = getFileByPath( path ); - if ( fileByPath != null ) { - if ( fileByPath.isFolder() ) { - FSEntry [] listEntries = fileByPath.asFolder().listEntries(); - for ( FSEntry entry : listEntries ) { - list.add( entry ); + FSEntry fileByPath = getFileByPath(path); + if (fileByPath != null) { + if (fileByPath.isFolder()) { + FSEntry[] listEntries = fileByPath.asFolder().listEntries(); + for (FSEntry entry : listEntries) { + list.add(entry); } } } @@ -343,58 +349,61 @@ public class DmgFileReader implements Closeable { } /** - * Returns the length of the given file system entry. + * {@return the length of the given file system entry} + *

* 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()) { FSFork mainFork = entry.asFile().getMainFork(); - if ( mainFork.getLength() > 0 ) { + if (mainFork.getLength() > 0) { return mainFork.getLength(); } - try { - if (parser != null) { - DecmpfsHeader header = parser.getDecmpfsHeader(entry.asFile()); - if (header != null) { - return header.getUncompressedSize(); - } + if (parser != null) { + DecmpfsHeader header = parser.getDecmpfsHeader(entry.asFile()); + if (header != null) { + return header.getUncompressedSize(); } } - catch (IOException e) { - return 1;//TODO lookup valid length in DECMPFS - } } return -1; } /** - * Convert path to string array. - * + * {@return a path converted to a string array} + *

* For example, "/a/b/c.txt" will be converted to [ "a", "b", "c.txt" ]. - * + *

* Note: the "a" will be stripped because it corresponds to the file system handler. + * + * @param path the path */ - public String [] convertPathToArrayAndStripFileSystemName( String path ) { - String [] splitPath = path.split( "/" ); - if ( splitPath.length <= 2 ) { - return new String[ 0 ]; + public String[] convertPathToArrayAndStripFileSystemName(String path) { + String[] splitPath = path.split("/"); + if (splitPath.length <= 2) { + return new String[0]; } - String [] temp = new String[ splitPath.length - 2 ]; - System.arraycopy( splitPath, 2, temp, 0, splitPath.length - 2 ); + String[] temp = new String[splitPath.length - 2]; + System.arraycopy(splitPath, 2, temp, 0, splitPath.length - 2); return temp; } /** - * Returns the DMG file object for the corresponding path. + * {@return the DMG file object for the corresponding path} + *

* Path should contain the file system handler name. + * + * @param path the path */ - public FSEntry getFileByPath( String path ) { - if ( path == null || path.equals( "/" ) ) {//ROOT + public FSEntry getFileByPath(String path) { + if (path == null || path.equals("/")) {//ROOT return null; } - for ( FileSystemHandler handler : fileSystemHandlers ) { - FSEntry entry = handler.getEntry( convertPathToArrayAndStripFileSystemName( path ) ); - if ( entry != null ) { + for (FileSystemHandler handler : fileSystemHandlers) { + FSEntry entry = handler.getEntry(convertPathToArrayAndStripFileSystemName(path)); + if (entry != null) { return entry; } } diff --git a/GPL/DMG/src/dmg/java/mobiledevices/dmg/reader/DmgInfoGenerator.java b/GPL/DMG/src/dmg/java/mobiledevices/dmg/reader/DmgInfoGenerator.java index 80b5a0c6fb..6b3c18bae0 100644 --- a/GPL/DMG/src/dmg/java/mobiledevices/dmg/reader/DmgInfoGenerator.java +++ b/GPL/DMG/src/dmg/java/mobiledevices/dmg/reader/DmgInfoGenerator.java @@ -3,7 +3,6 @@ */ package mobiledevices.dmg.reader; -import java.io.IOException; import java.text.DateFormat; import java.util.ArrayList; import java.util.List; @@ -20,9 +19,7 @@ import mobiledevices.dmg.decmpfs.DecmpfsHeader; import mobiledevices.dmg.hfsplus.AttributesFileParser; /** - * * @see org.catacombae.hfsexplorer.gui.FSEntrySummaryPanel - * */ class DmgInfoGenerator { private DmgFileReader fileSystem; @@ -60,14 +57,10 @@ class DmgInfoGenerator { appendFileID(infoList, file); if (parser != null) { - try { - DecmpfsHeader decmpfsHeader = parser.getDecmpfsHeader(file); - if (decmpfsHeader != null) { - infoList.add( - "Decmpfs Size: " + getSizeString(decmpfsHeader.getUncompressedSize())); - } - } - catch (IOException e) { + DecmpfsHeader decmpfsHeader = parser.getDecmpfsHeader(file); + if (decmpfsHeader != null) { + infoList.add( + "Decmpfs Size: " + getSizeString(decmpfsHeader.getUncompressedSize())); } } } @@ -201,21 +194,21 @@ class DmgInfoGenerator { } private void calculateFolderSize(FSFolder folder, ObjectContainer result) { - for (FSEntry entry : folder.listEntries()) { - if (entry instanceof FSFile) { + for (FSEntry e : folder.listEntries()) { + if (e instanceof FSFile) { Long value = result.o; - value += ((FSFile) entry).getMainFork().getLength(); + value += ((FSFile) e).getMainFork().getLength(); result.o = value; } - else if (entry instanceof FSFolder) { - calculateFolderSize((FSFolder) entry, result); + else if (e instanceof FSFolder) { + 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. */ } else { System.err.println("FSEntrySummaryPanel.calculateFolderSize():" + - " unexpected type " + entry.getClass()); + " unexpected type " + e.getClass()); } } }