GP-907 Add getByteProvider(GFile) to some file systems.

This commit adds getByteProvider(GFile) to a first batch of filesystems.  Remaining filesystems will be addressed in future commits.
This commit is contained in:
dev747368 2021-04-30 13:05:35 -04:00
parent f91ba90fe8
commit 3c73f252cb
15 changed files with 403 additions and 202 deletions

View file

@ -17,6 +17,8 @@ package ghidra.app.util.bin;
import java.io.*;
import ghidra.formats.gfilesystem.FSRL;
/**
* An implementation of {@link ByteProvider} where the underlying bytes are supplied by a static
* byte array.
@ -26,6 +28,7 @@ import java.io.*;
public class ByteArrayProvider implements ByteProvider {
private byte[] srcBytes;
private String name;
private FSRL fsrl;
/**
* Constructs a {@link ByteArrayProvider} using the specified byte array
@ -33,7 +36,18 @@ public class ByteArrayProvider implements ByteProvider {
* @param bytes the underlying byte array
*/
public ByteArrayProvider(byte[] bytes) {
this(bytes, null);
}
/**
* Constructs a {@link ByteArrayProvider} using the specified byte array
*
* @param bytes the underlying byte array
* @param fsrl FSRL identity of the file
*/
public ByteArrayProvider(byte[] bytes, FSRL fsrl) {
this.srcBytes = bytes;
this.fsrl = fsrl;
}
/**
@ -52,6 +66,11 @@ public class ByteArrayProvider implements ByteProvider {
// don't do anything for now
}
@Override
public FSRL getFSRL() {
return fsrl;
}
@Override
public File getFile() {
return null;

View file

@ -17,6 +17,8 @@ package ghidra.app.util.bin;
import java.io.*;
import ghidra.formats.gfilesystem.FSRL;
/**
* Creates a {@link ByteProvider} constrained to a sub-section of an existing {@link ByteProvider}.
*/
@ -24,6 +26,7 @@ public class ByteProviderWrapper implements ByteProvider {
private ByteProvider provider;
private long subOffset;
private long subLength;
private FSRL fsrl;
/**
* Constructs a {@link ByteProviderWrapper} around the specified {@link ByteProvider}
@ -34,9 +37,23 @@ public class ByteProviderWrapper implements ByteProvider {
* @param subLength the length of the new {@link ByteProviderWrapper}
*/
public ByteProviderWrapper(ByteProvider provider, long subOffset, long subLength) {
this(provider, subOffset, subLength, null);
}
/**
* Constructs a {@link ByteProviderWrapper} around the specified {@link ByteProvider}
*
* @param provider the {@link ByteProvider} to wrap
* @param subOffset the offset in the {@link ByteProvider} of where to start the new
* {@link ByteProviderWrapper}
* @param subLength the length of the new {@link ByteProviderWrapper}
* @param fsrl FSRL identity of the file this ByteProvider represents
*/
public ByteProviderWrapper(ByteProvider provider, long subOffset, long subLength, FSRL fsrl) {
this.provider = provider;
this.subOffset = subOffset;
this.subLength = subLength;
this.fsrl = fsrl;
}
@Override
@ -44,6 +61,11 @@ public class ByteProviderWrapper implements ByteProvider {
// don't do anything for now
}
@Override
public FSRL getFSRL() {
return fsrl;
}
@Override
public File getFile() {
return provider.getFile();
@ -51,7 +73,7 @@ public class ByteProviderWrapper implements ByteProvider {
@Override
public InputStream getInputStream(long index) throws IOException {
return provider.getInputStream(subOffset + index);
return new ByteProviderInputStream(this, index, subLength - index);
}
@Override

View file

@ -59,6 +59,16 @@ public class SingleFileSystemIndexHelper {
payloadFile = null;
}
/**
* Returns true if the specified file is the payload file.
*
* @param file GFile to test
* @return boolean true if it is the payload file
*/
public boolean isPayloadFile(GFile file) {
return payloadFile.equals(file);
}
/**
* Returns true if this object has been {@link #clear()}'ed.
*

View file

@ -20,7 +20,7 @@ import java.io.InputStream;
import java.util.*;
import ghidra.app.util.bin.ByteProvider;
import ghidra.app.util.bin.ByteProviderInputStream;
import ghidra.app.util.bin.ByteProviderWrapper;
import ghidra.app.util.bin.format.coff.CoffException;
import ghidra.app.util.bin.format.coff.archive.CoffArchiveHeader;
import ghidra.app.util.bin.format.coff.archive.CoffArchiveMemberHeader;
@ -77,9 +77,15 @@ public class CoffArchiveFileSystem implements GFileSystem {
public InputStream getInputStream(GFile file, TaskMonitor monitor)
throws IOException, CancelledException {
ByteProvider bp = getByteProvider(file, monitor);
return bp != null ? bp.getInputStream(0) : null;
}
public ByteProvider getByteProvider(GFile file, TaskMonitor monitor) {
CoffArchiveMemberHeader entry = fsih.getMetadata(file);
return (entry != null && entry.isCOFF())
? new ByteProviderInputStream(provider, entry.getPayloadOffset(), entry.getSize())
? new ByteProviderWrapper(provider, entry.getPayloadOffset(), entry.getSize(),
file.getFSRL())
: null;
}

View file

@ -16,71 +16,91 @@
package ghidra.file.formats.complzss;
import java.io.*;
import java.util.*;
import java.util.List;
import ghidra.app.util.bin.ByteArrayProvider;
import ghidra.app.util.bin.ByteProvider;
import ghidra.file.formats.lzss.LzssCodec;
import ghidra.file.formats.lzss.LzssConstants;
import ghidra.formats.gfilesystem.*;
import ghidra.formats.gfilesystem.annotations.FileSystemInfo;
import ghidra.formats.gfilesystem.factory.GFileSystemBaseFactory;
import ghidra.util.HashUtilities;
import ghidra.util.exception.CancelledException;
import ghidra.util.exception.CryptoException;
import ghidra.util.task.TaskMonitor;
@FileSystemInfo(type = "lzss", description = "LZSS Compression", factory = GFileSystemBaseFactory.class)
public class CompLzssFileSystem extends GFileSystemBase {
@FileSystemInfo(type = "lzss", description = "LZSS Compression", factory = CompLzssFileSystemFactory.class)
public class CompLzssFileSystem implements GFileSystem {
private FSRLRoot fsFSRL;
private SingleFileSystemIndexHelper fsIndex;
private FileSystemRefManager fsRefManager = new FileSystemRefManager(this);
private ByteProvider payloadProvider;
private static final String NAME = "lzss_decompressed";
private GFileImpl decompressedFile;
private byte[] decompressedBytes;
public CompLzssFileSystem(String fileSystemName, ByteProvider provider) {
super(fileSystemName, provider);
}
@Override
public void close() throws IOException {
decompressedFile = null;
decompressedBytes = null;
}
@Override
protected InputStream getData(GFile file, TaskMonitor monitor)
throws IOException, CancelledException, CryptoException {
if (file != null && file.equals(decompressedFile)) {
return new ByteArrayInputStream(decompressedBytes);
}
return null;
}
@Override
public List<GFile> getListing(GFile directory) throws IOException {
return (directory == null || directory.equals(root)) ? Arrays.asList(decompressedFile)
: Collections.emptyList();
}
@Override
public boolean isValid(TaskMonitor monitor) throws IOException {
byte[] compressionBytes = provider.readBytes(0, 4);
byte[] lzssBytes = provider.readBytes(4, 4);
return Arrays.equals(compressionBytes, LzssConstants.SIGNATURE_COMPRESSION_BYTES) &&
Arrays.equals(lzssBytes, LzssConstants.SIGNATURE_LZSS_BYTES);
}
@Override
public void open(TaskMonitor monitor) throws IOException, CryptoException, CancelledException {
public CompLzssFileSystem(FSRLRoot fsrl, ByteProvider provider, TaskMonitor monitor)
throws IOException {
monitor.setMessage("Decompressing LZSS...");
byte[] compressedBytes = provider.readBytes(LzssConstants.HEADER_LENGTH,
provider.length() - LzssConstants.HEADER_LENGTH);
ByteArrayOutputStream decompressedBOS = new ByteArrayOutputStream();
LzssCodec.decompress(decompressedBOS, new ByteArrayInputStream(compressedBytes));
decompressedBytes = decompressedBOS.toByteArray();
decompressedFile =
GFileImpl.fromFilename(this, root, NAME, false, decompressedBytes.length, null);
debug(decompressedBytes, NAME);
byte[] decompressedBytes = decompressedBOS.toByteArray();
String md5 = HashUtilities.getHash(HashUtilities.MD5_ALGORITHM, decompressedBytes);
this.fsIndex = new SingleFileSystemIndexHelper(this, fsFSRL, "lzss_decompressed",
decompressedBytes.length, md5);
this.payloadProvider =
new ByteArrayProvider(decompressedBytes, fsIndex.getPayloadFile().getFSRL());
}
@Override
public FSRLRoot getFSRL() {
return fsFSRL;
}
@Override
public String getName() {
return fsFSRL.getContainer().getName();
}
@Override
public FileSystemRefManager getRefManager() {
return fsRefManager;
}
@Override
public boolean isClosed() {
return payloadProvider == null;
}
@Override
public void close() throws IOException {
fsRefManager.onClose();
if (payloadProvider != null) {
payloadProvider.close();
payloadProvider = null;
}
fsIndex.clear();
}
@Override
public InputStream getInputStream(GFile file, TaskMonitor monitor)
throws IOException, CancelledException {
ByteProvider bp = getByteProvider(file, monitor);
return bp != null ? bp.getInputStream(0) : null;
}
public ByteProvider getByteProvider(GFile file, TaskMonitor monitor) {
return fsIndex.isPayloadFile(file) ? payloadProvider : null;
}
@Override
public List<GFile> getListing(GFile directory) throws IOException {
return fsIndex.getListing(directory);
}
@Override
public GFile lookup(String path) throws IOException {
return fsIndex.lookup(path);
}
}

View file

@ -0,0 +1,50 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.file.formats.complzss;
import java.io.File;
import java.io.IOException;
import ghidra.app.util.bin.ByteProvider;
import ghidra.file.formats.lzss.LzssCompressionHeader;
import ghidra.formats.gfilesystem.*;
import ghidra.formats.gfilesystem.factory.GFileSystemFactoryFull;
import ghidra.formats.gfilesystem.factory.GFileSystemProbeBytesOnly;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
public class CompLzssFileSystemFactory
implements GFileSystemFactoryFull<CompLzssFileSystem>, GFileSystemProbeBytesOnly {
@Override
public CompLzssFileSystem create(FSRL containerFSRL, FSRLRoot targetFSRL,
ByteProvider byteProvider, File containerFile, FileSystemService fsService,
TaskMonitor monitor) throws IOException, CancelledException {
CompLzssFileSystem fs = new CompLzssFileSystem(targetFSRL, byteProvider, monitor);
return fs;
}
@Override
public int getBytesRequired() {
return LzssCompressionHeader.PROBE_BYTES_NEEDED;
}
@Override
public boolean probeStartBytes(FSRL containerFSRL, byte[] startBytes) {
return LzssCompressionHeader.probe(startBytes);
}
}

View file

@ -16,86 +16,107 @@
package ghidra.file.formats.cpio;
import java.io.*;
import java.util.*;
import java.util.Date;
import java.util.List;
import org.apache.commons.compress.archivers.cpio.CpioArchiveEntry;
import org.apache.commons.compress.archivers.cpio.CpioArchiveInputStream;
import ghidra.app.util.bin.ByteArrayProvider;
import ghidra.app.util.bin.ByteProvider;
import ghidra.formats.gfilesystem.*;
import ghidra.formats.gfilesystem.FSUtilities.StreamCopyResult;
import ghidra.formats.gfilesystem.annotations.FileSystemInfo;
import ghidra.formats.gfilesystem.factory.GFileSystemBaseFactory;
import ghidra.util.NumericUtilities;
import ghidra.util.exception.CancelledException;
import ghidra.util.exception.CryptoException;
import ghidra.util.task.TaskMonitor;
import utilities.util.FileUtilities;
@FileSystemInfo(type = "cpio", description = "CPIO", factory = GFileSystemBaseFactory.class)
public class CpioFileSystem extends GFileSystemBase {
@FileSystemInfo(type = "cpio", description = "CPIO", factory = CpioFileSystemFactory.class)
public class CpioFileSystem implements GFileSystem {
private FSRLRoot fsFSRL;
private FileSystemIndexHelper<CpioArchiveEntry> fsIndex;
private FileSystemRefManager fsRefManager = new FileSystemRefManager(this);
private ByteProvider provider;
private Map<GFile, CpioArchiveEntry> map = new HashMap<>();
public CpioFileSystem(String fileSystemName, ByteProvider provider) {
super(fileSystemName, provider);
}
@Override
public boolean isValid(TaskMonitor monitor) throws IOException {
byte[] signature = provider.readBytes(0, 0x10);
return CpioArchiveInputStream.matches(signature, 0x10);
}
@Override
public void open(TaskMonitor monitor) throws IOException, CryptoException, CancelledException {
public CpioFileSystem(FSRLRoot fsFSRL, ByteProvider provider, TaskMonitor monitor)
throws IOException {
monitor.setMessage("Opening CPIO...");
this.fsFSRL = fsFSRL;
this.provider = provider;
this.fsIndex = new FileSystemIndexHelper<>(this, fsFSRL);
try (CpioArchiveInputStream cpioInputStream =
new CpioArchiveInputStream(provider.getInputStream(0))) {
CpioArchiveEntry entry;
int fileNum = 0;
while ((entry = cpioInputStream.getNextCPIOEntry()) != null) {
skipEntryContents(cpioInputStream, monitor);
storeEntry(entry, monitor);
FileUtilities.copyStreamToStream(cpioInputStream, OutputStream.nullOutputStream(),
monitor);
monitor.setMessage(entry.getName());
fsIndex.storeFile(entry.getName(), fileNum++, entry.isDirectory(),
entry.getSize(), entry);
}
}
catch (EOFException e) {
// silently ignore EOFExceptions
}
catch (IOException e) {
throw e;
}
catch (Exception e) {
FSUtilities.displayException(this, null, "Error While Opening CPIO", e.getMessage(), e);
throw new IOException(e);
}
}
@Override
public void close() throws IOException {
super.close();
map.clear();
fsRefManager.onClose();
fsIndex.clear();
if (provider != null) {
provider.close();
provider = null;
}
}
@Override
public FSRLRoot getFSRL() {
return fsFSRL;
}
@Override
public String getName() {
return fsFSRL.getContainer().getName();
}
@Override
public boolean isClosed() {
return provider == null;
}
@Override
public FileSystemRefManager getRefManager() {
return fsRefManager;
}
@Override
public List<GFile> getListing(GFile directory) throws IOException {
if (directory == null || directory.equals(root)) {
List<GFile> roots = new ArrayList<>();
for (GFile file : map.keySet()) {
if (file.getParentFile() == root || file.getParentFile().equals(root)) {
roots.add(file);
}
}
return roots;
}
List<GFile> tmp = new ArrayList<>();
for (GFile file : map.keySet()) {
if (file.getParentFile() == null) {
continue;
}
if (file.getParentFile().equals(directory)) {
tmp.add(file);
}
}
return tmp;
return fsIndex.getListing(directory);
}
@Override
public GFile lookup(String path) throws IOException {
return fsIndex.lookup(path);
}
@Override
public String getInfo(GFile file, TaskMonitor monitor) {
CpioArchiveEntry entry = map.get(file);
CpioArchiveEntry entry = fsIndex.getMetadata(file);
if (entry == null) {
return null;
}
StringBuilder buffer = new StringBuilder();
try {
buffer.append("Name: " + entry.getName() + "\n");
@ -129,84 +150,46 @@ public class CpioFileSystem extends GFileSystemBase {
}
@Override
protected InputStream getData(GFile file, TaskMonitor monitor)
throws IOException, CancelledException, CryptoException {
CpioArchiveEntry fileEntry = map.get(file);
if (!fileEntry.isRegularFile()) {
public InputStream getInputStream(GFile file, TaskMonitor monitor)
throws IOException, CancelledException {
ByteProvider bp = getByteProvider(file, monitor);
return bp != null ? bp.getInputStream(0) : null;
}
public ByteProvider getByteProvider(GFile file, TaskMonitor monitor)
throws IOException, CancelledException {
CpioArchiveEntry targetEntry = fsIndex.getMetadata(file);
if (targetEntry == null) {
return null;
}
if (!targetEntry.isRegularFile()) {
throw new IOException("CPIO entry " + file.getName() + " is not a regular file.");
}
try (CpioArchiveInputStream cpioInputStream =
new CpioArchiveInputStream(provider.getInputStream(0));) {
new CpioArchiveInputStream(provider.getInputStream(0))) {
CpioArchiveEntry entry;
while ((entry = cpioInputStream.getNextCPIOEntry()) != null) {
if (!entry.equals(fileEntry)) {
skipEntryContents(cpioInputStream, monitor);
}
else {
byte[] entryBytes = readEntryContents(cpioInputStream, monitor);
return new ByteArrayInputStream(entryBytes);
CpioArchiveEntry currentEntry;
while ((currentEntry = cpioInputStream.getNextCPIOEntry()) != null) {
if (currentEntry.equals(targetEntry)) {
return getByteProviderForEntry(cpioInputStream, file.getFSRL(), monitor);
}
FileUtilities.copyStreamToStream(cpioInputStream, OutputStream.nullOutputStream(),
monitor);
}
}
catch (IllegalArgumentException e) {
//unknown MODES..
throw new IOException(e);
}
return null;
throw new IOException("Unable to seek to entry: " + file.getName());
}
private void storeEntry(CpioArchiveEntry entry, TaskMonitor monitor) {
monitor.setMessage(entry.getName());
GFileImpl file = GFileImpl.fromPathString(this, root, entry.getName(), null,
entry.isDirectory(), entry.getSize());
storeFile(file, entry, monitor);
}
private void storeFile(GFile file, CpioArchiveEntry entry, TaskMonitor monitor) {
if (monitor.isCancelled()) {
return;
}
if (file == null) {
return;
}
if (file.equals(root)) {
return;
}
if (!map.containsKey(file) || map.get(file) == null) {
map.put(file, entry);
}
GFile parentFile = file.getParentFile();
storeFile(parentFile, null, monitor);
}
private byte[] readEntryContents(CpioArchiveInputStream cpioInputStream, TaskMonitor monitor)
throws IOException, CancelledException {
private ByteProvider getByteProviderForEntry(CpioArchiveInputStream cpioInputStream, FSRL fsrl,
TaskMonitor monitor) throws CancelledException, IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buffer = new byte[64 * 1024];
while (true) {
if (monitor.isCancelled()) {
throw new CancelledException();
}
int bytesRead = cpioInputStream.read(buffer);
if (bytesRead <= 0) {
break;
}
out.write(buffer, 0, bytesRead);
}
return out.toByteArray();
}
private void skipEntryContents(CpioArchiveInputStream cpioInputStream, TaskMonitor monitor)
throws IOException, CancelledException {
byte[] buffer = new byte[64 * 1024];
while (true) {
if (monitor.isCancelled()) {
throw new CancelledException();
}
int bytesRead = cpioInputStream.read(buffer);
if (bytesRead <= 0) {
break;
}
StreamCopyResult copyResult = FSUtilities.streamCopy(cpioInputStream, out, monitor);
if (fsrl.getMD5() == null) {
fsrl = fsrl.withMD5(NumericUtilities.convertBytesToString(copyResult.md5));
}
return new ByteArrayProvider(out.toByteArray(), fsrl);
}
}

View file

@ -0,0 +1,51 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.file.formats.cpio;
import java.io.File;
import java.io.IOException;
import org.apache.commons.compress.archivers.cpio.CpioArchiveInputStream;
import ghidra.app.util.bin.ByteProvider;
import ghidra.formats.gfilesystem.*;
import ghidra.formats.gfilesystem.factory.GFileSystemFactoryFull;
import ghidra.formats.gfilesystem.factory.GFileSystemProbeBytesOnly;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
public class CpioFileSystemFactory
implements GFileSystemFactoryFull<CpioFileSystem>, GFileSystemProbeBytesOnly {
@Override
public CpioFileSystem create(FSRL containerFSRL, FSRLRoot targetFSRL,
ByteProvider byteProvider, File containerFile, FileSystemService fsService,
TaskMonitor monitor) throws IOException, CancelledException {
CpioFileSystem fs = new CpioFileSystem(targetFSRL, byteProvider, monitor);
return fs;
}
@Override
public int getBytesRequired() {
return 6; // CpioArchiveInputStream doesn't have a value we can use, so we hard code
}
@Override
public boolean probeStartBytes(FSRL containerFSRL, byte[] startBytes) {
return CpioArchiveInputStream.matches(startBytes, startBytes.length);
}
}

View file

@ -46,7 +46,6 @@ public class GZipFileSystem implements GFileSystem {
private final SingleFileSystemIndexHelper fsIndex;
private final FileSystemService fsService;
private GFile payload;
private String origFilename;
private String payloadKey;
private String origComment;
@ -64,7 +63,6 @@ public class GZipFileSystem implements GFileSystem {
FileCacheEntry fce = getPayloadFileCacheEntry(monitor);
this.fsIndex =
new SingleFileSystemIndexHelper(this, fsFSRL, origFilename, fce.file.length(), fce.md5);
this.payload = fsIndex.getPayloadFile();
}
private void readGzipMetadata(File containerFile, TaskMonitor monitor) throws IOException {
@ -101,7 +99,7 @@ public class GZipFileSystem implements GFileSystem {
}
public GFile getPayloadFile() {
return payload;
return fsIndex.getPayloadFile();
}
@Override
@ -118,7 +116,6 @@ public class GZipFileSystem implements GFileSystem {
public void close() throws IOException {
refManager.onClose();
fsIndex.clear();
payload = null;
}
@Override
@ -134,7 +131,7 @@ public class GZipFileSystem implements GFileSystem {
@Override
public InputStream getInputStream(GFile file, TaskMonitor monitor)
throws IOException, CancelledException {
if (payload.equals(file)) {
if (fsIndex.isPayloadFile(file)) {
FileCacheEntry fce = getPayloadFileCacheEntry(monitor);
return new FileInputStream(fce.file);
}
@ -148,13 +145,14 @@ public class GZipFileSystem implements GFileSystem {
@Override
public String getInfo(GFile file, TaskMonitor monitor) {
if (payload.equals(file)) {
if (fsIndex.isPayloadFile(file)) {
return FSUtilities.infoMapToString(getInfoMap());
}
return null;
}
public Map<String, String> getInfoMap() {
GFile payload = fsIndex.getPayloadFile();
Map<String, String> info = new LinkedHashMap<>();
info.put("Name", payload.getName());
info.put("Size", Long.toString(payload.getLength()));

View file

@ -15,14 +15,15 @@
*/
package ghidra.file.formats.iso9660;
import ghidra.app.util.bin.*;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
import java.io.*;
import java.io.IOException;
import java.time.DateTimeException;
import java.time.LocalDateTime;
import ghidra.app.util.bin.*;
import ghidra.formats.gfilesystem.FSRL;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
public class ISO9660Directory implements StructConverter {
private int directoryRecordLength;
@ -175,21 +176,11 @@ public class ISO9660Directory implements StructConverter {
return false;
}
/**
* Returns the bytes of the file which this directory points to
* @param provider The ByteProvider
* @param logicalBlockSize
* @return An InputStream of the data bytes
* @throws IOException
*/
public InputStream getDataBytes(ByteProvider provider, long logicalBlockSize)
throws IOException {
ByteProvider getByteProvider(ByteProvider provider, long logicalBlockSize, FSRL fsrl) {
if (!(this.isDirectoryFlagSet())) {
if (!this.isDirectoryFlagSet()) {
long index = locationOfExtentLE * logicalBlockSize;
byte[] dataBytes = provider.readBytes(index, dataLengthLE);
InputStream inputStream = new ByteArrayInputStream(dataBytes);
return inputStream;
return new ByteProviderWrapper(provider, index, dataLengthLE, fsrl);
}
return null;
}

View file

@ -15,10 +15,9 @@
*/
package ghidra.file.formats.iso9660;
import java.util.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.ByteProvider;
@ -148,10 +147,14 @@ public class ISO9660FileSystem extends GFileSystemBase {
protected InputStream getData(GFile file, TaskMonitor monitor)
throws IOException, CancelledException, CryptoException {
ISO9660Directory dir = fileToDirectoryMap.get(file);
InputStream inputStream = dir.getDataBytes(provider, logicalBlockSize);
ByteProvider bp = getByteProvider(file, monitor);
return bp != null ? bp.getInputStream(0) : null;
}
return inputStream;
public ByteProvider getByteProvider(GFile file, TaskMonitor monitor)
throws IOException, CancelledException {
ISO9660Directory dir = fileToDirectoryMap.get(file);
return dir.getByteProvider(provider, logicalBlockSize, file.getFSRL());
}
/*

View file

@ -126,7 +126,7 @@ public class JavaClassDecompilerFileSystem implements GFileSystem {
@Override
public InputStream getInputStream(GFile file, TaskMonitor monitor)
throws IOException, CancelledException {
if (fsIndexHelper.getPayloadFile().equals(file)) {
if (fsIndexHelper.isPayloadFile(file)) {
FileCacheEntry fce = getDecompiledJavaSrcFileEntry(monitor);
return new FileInputStream(fce.file);
}
@ -140,7 +140,7 @@ public class JavaClassDecompilerFileSystem implements GFileSystem {
@Override
public String getInfo(GFile file, TaskMonitor monitor) {
if (fsIndexHelper.getPayloadFile().equals(file)) {
if (fsIndexHelper.isPayloadFile(file)) {
Map<String, String> info = new HashMap<>();
info.put("Class name", className);
return FSUtilities.infoMapToString(info);

View file

@ -15,20 +15,46 @@
*/
package ghidra.file.formats.lzss;
import java.io.IOException;
import ghidra.app.util.bin.*;
import ghidra.program.model.data.DataType;
import ghidra.util.exception.DuplicateNameException;
import java.io.IOException;
public class LzssCompressionHeader implements StructConverter {
private int signature;
private int compressionType;
private int checksum;
private int decompressedLength;
private int compressedLength;
private byte [] padding;
public static final int PROBE_BYTES_NEEDED = 8; // sizeof(signature) + sizeof(compressionType)
/**
* Returns true if the bytes have the magic signature of a LzssCompressionHeader.
*
* @param startBytes byte array
* @return boolean true if the signature of a LzssCompressionHeader appears at the beginning
* the byte array
*/
public static boolean probe(byte[] startBytes) {
try {
if (startBytes.length < PROBE_BYTES_NEEDED) {
return false;
}
BinaryReader reader = new BinaryReader(new ByteArrayProvider(startBytes), false);
int signature = reader.readNextInt();
int compressionType = reader.readNextInt();
return signature == LzssConstants.SIGNATURE_LZSS &&
compressionType == LzssConstants.SIGNATURE_COMPRESSION;
}
catch (IOException e) {
return false;
}
}
private int signature;
private int compressionType;
private int checksum;
private int decompressedLength;
private int compressedLength;
private byte[] padding;
public LzssCompressionHeader(ByteProvider provider) throws IOException {
BinaryReader reader = new BinaryReader(provider, false);
@ -60,6 +86,7 @@ public class LzssCompressionHeader implements StructConverter {
return padding;
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
return StructConverterUtil.toDataType(this);
}

View file

@ -98,9 +98,15 @@ public class OmfArchiveFileSystem implements GFileSystem {
public InputStream getInputStream(GFile file, TaskMonitor monitor)
throws IOException, CancelledException {
ByteProvider bp = getByteProvider(file, monitor);
return bp != null ? bp.getInputStream(0) : null;
}
public ByteProvider getByteProvider(GFile file, TaskMonitor monitor) {
OmfLibraryRecord.MemberHeader member = fsih.getMetadata(file);
return (member != null)
? new ByteProviderInputStream(provider, member.payloadOffset, member.size)
? new ByteProviderWrapper(provider, member.payloadOffset, member.size,
file.getFSRL())
: null;
}

View file

@ -170,6 +170,21 @@ public class HashUtilities {
return NumericUtilities.convertBytesToString(messageDigest.digest());
}
/**
* Generate combined message digest hash for the bytes in the specified array.
*
* @param algorithm message digest algorithm
* @param values array of bytes to hash
* @return message digest hash
* @throws IllegalArgumentException if specified algorithm is not supported
* @see MessageDigest for supported hash algorithms
*/
public static String getHash(String algorithm, byte[] values) {
MessageDigest messageDigest = getMessageDigest(algorithm);
messageDigest.update(values);
return NumericUtilities.convertBytesToString(messageDigest.digest());
}
private static MessageDigest getMessageDigest(String algorithm) {
try {
return MessageDigest.getInstance(algorithm);