Skip to content

Commit 3c12ffa

Browse files
committed
Add type selection fallback for fs open.
Right now it is not possible to either force or to pick a filesystem provider that does not have content probing facilities. This patch adds a fallback filesystem provider selection choice screen populated with filesystems that are available but do not probe their contents if no probing filesystem claimed the resource in question.
1 parent 69b0716 commit 3c12ffa

File tree

4 files changed

+94
-4
lines changed

4 files changed

+94
-4
lines changed

Ghidra/Features/Base/src/main/java/ghidra/formats/gfilesystem/FileSystemService.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -962,4 +962,17 @@ public synchronized CryptoSession newCryptoSession() {
962962
return new CryptoProviderSessionChildImpl(currentCryptoSession);
963963
}
964964

965+
/**
966+
* Adds the given {@link GFileSystem} instance to the managed filesystems list.
967+
*
968+
* @param fs {@link GFileSystem} to add to the managed filesystems list.
969+
*/
970+
public void addFileSystem(GFileSystem fs) {
971+
synchronized (fsInstanceManager) {
972+
if (!isFilesystemMountedAt(fs.getFSRL())) {
973+
fsInstanceManager.add(fs);
974+
}
975+
}
976+
}
977+
965978
}

Ghidra/Features/Base/src/main/java/ghidra/formats/gfilesystem/factory/FileSystemFactoryMgr.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,4 +347,12 @@ public GFileSystem probe(ByteProvider byteProvider, FileSystemService fsService,
347347

348348
}
349349

350+
/**
351+
* Returns the filesystem providers available to this factory.
352+
*
353+
* @return a copy of the available filesystem providers.
354+
*/
355+
public Map<String, FileSystemInfoRec> getFileSystemInfoRecs() {
356+
return new HashMap<>(fsByType);
357+
}
350358
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/* ###
2+
* IP: GHIDRA
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package ghidra.formats.gfilesystem.factory;
17+
18+
/**
19+
* A {@link GFileSystemProbe} interface for filesystems that can be directly
20+
* chosen by the user as a fallback if automatic filesystem detection fails.
21+
*/
22+
public interface GFileSystemProbeManual extends GFileSystemProbe {
23+
// Empty interface.
24+
}

Ghidra/Features/Base/src/main/java/ghidra/plugins/fsbrowser/FileSystemBrowserPlugin.java

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
package ghidra.plugins.fsbrowser;
1717

1818
import java.util.*;
19-
19+
import java.util.stream.Collectors;
2020
import java.awt.Component;
2121
import java.awt.event.InputEvent;
2222
import java.awt.event.KeyEvent;
@@ -35,8 +35,14 @@
3535
import ghidra.app.events.ProgramActivatedPluginEvent;
3636
import ghidra.app.plugin.PluginCategoryNames;
3737
import ghidra.app.services.*;
38+
import ghidra.app.util.bin.ByteProvider;
3839
import ghidra.app.util.opinion.LoaderService;
3940
import ghidra.formats.gfilesystem.*;
41+
import ghidra.formats.gfilesystem.factory.FileSystemFactoryMgr;
42+
import ghidra.formats.gfilesystem.factory.FileSystemInfoRec;
43+
import ghidra.formats.gfilesystem.factory.GFileSystemProbeByteProvider;
44+
import ghidra.formats.gfilesystem.factory.GFileSystemProbeBytesOnly;
45+
import ghidra.formats.gfilesystem.factory.GFileSystemProbeManual;
4046
import ghidra.framework.main.FrontEndService;
4147
import ghidra.framework.main.ApplicationLevelPlugin;
4248
import ghidra.framework.model.Project;
@@ -244,9 +250,12 @@ private void doOpenFilesystem(FSRL containerFSRL, Component parent, TaskMonitor
244250
FileSystemRef ref = fsService().probeFileForFilesystem(containerFSRL, monitor,
245251
FileSystemProbeConflictResolver.GUI_PICKER);
246252
if (ref == null) {
247-
Msg.showWarn(this, parent, "Open Filesystem",
248-
"No filesystem provider for " + containerFSRL.getName());
249-
return;
253+
ref = showFallbackFileSystemChooser(containerFSRL, parent, monitor);
254+
if (ref == null) {
255+
Msg.showWarn(this, parent, "Open Filesystem",
256+
"No filesystem provider for " + containerFSRL.getName());
257+
return;
258+
}
250259
}
251260

252261
createNewFileSystemBrowser(ref, true);
@@ -257,6 +266,42 @@ private void doOpenFilesystem(FSRL containerFSRL, Component parent, TaskMonitor
257266
}
258267
}
259268

269+
private FileSystemRef showFallbackFileSystemChooser(FSRL containerFSRL, Component parent, TaskMonitor monitor) throws CancelledException, IOException {
270+
FileSystemFactoryMgr fsFactoryMgr = FileSystemFactoryMgr.getInstance();
271+
272+
//@formatter:off
273+
List<FileSystemInfoRec> fsList = fsFactoryMgr.getFileSystemInfoRecs().values()
274+
.stream()
275+
.filter(fs -> fs.getFactory() instanceof GFileSystemProbeManual)
276+
.sorted((filesystem1, filesystem2) -> filesystem1.getDescription().compareToIgnoreCase(filesystem2.getDescription()))
277+
.collect(Collectors.toList());
278+
//@formatter:on
279+
280+
if (fsList.isEmpty()) {
281+
return null;
282+
}
283+
284+
FileSystemInfoRec chosenFilesystem = SelectFromListDialog.selectFromList(fsList, "Select filesystem",
285+
"Select a filesystem from list", FileSystemInfoRec::getDescription);
286+
if (chosenFilesystem == null) {
287+
return null;
288+
}
289+
290+
ByteProvider byteProvider = fsService().getByteProvider(containerFSRL, true, monitor);
291+
GFileSystem fs = fsFactoryMgr.mountFileSystem(chosenFilesystem.getType(), byteProvider, fsService, monitor);
292+
if (fs != null) {
293+
FileSystemRef fsRef = fsService().getMountedFilesystem(containerFSRL.makeNested(chosenFilesystem.getType()));
294+
if (fsRef != null) {
295+
fs.close();
296+
return fsRef;
297+
}
298+
fsService().addFileSystem(fs);
299+
return fs.getRefManager().create();
300+
}
301+
302+
return null;
303+
}
304+
260305
/**
261306
* Prompts the user to pick a file system container file to open using a local
262307
* filesystem browser and then displays that filesystem in a new fsb browser.

0 commit comments

Comments
 (0)