Merge remote-tracking branch 'origin/GP-650_jpleasu_fix_symbolic_links_to_scripts--SQUASHED'

This commit is contained in:
ghidra1 2021-02-01 18:06:06 -05:00
commit 33d29e4cac
4 changed files with 75 additions and 23 deletions

View file

@ -47,6 +47,7 @@ import generic.io.NullPrintWriter;
import generic.jar.ResourceFile; import generic.jar.ResourceFile;
import ghidra.app.script.*; import ghidra.app.script.*;
import ghidra.util.Msg; import ghidra.util.Msg;
import utilities.util.FileUtilities;
/** /**
* {@link GhidraSourceBundle} represents a Java source directory that is compiled on build to an OSGi bundle. * {@link GhidraSourceBundle} represents a Java source directory that is compiled on build to an OSGi bundle.
@ -173,20 +174,18 @@ public class GhidraSourceBundle extends GhidraBundle {
* *
* @param sourceFile a source file from this bundle * @param sourceFile a source file from this bundle
* @return the class name * @return the class name
* @throws ClassNotFoundException if {@code sourceFile} isn't contained in this bundle
*/ */
public String classNameForScript(ResourceFile sourceFile) { public String classNameForScript(ResourceFile sourceFile) throws ClassNotFoundException {
try { String relativePath = FileUtilities.relativizePath(getSourceDirectory(), sourceFile);
String path = sourceFile.getCanonicalPath(); if (relativePath == null) {
throw new ClassNotFoundException(
// get the relative path and chop ".java" from the end String.format("Failed to find script file '%s' in source directory '%s'",
path = path.substring(1 + getSourceDirectory().getCanonicalPath().length(), sourceFile, getSourceDirectory()));
path.length() - 5);
return path.replace(File.separatorChar, '.');
}
catch (IOException e) {
Msg.error(this, "getting class name for script", e);
return null;
} }
// chop ".java" from the end
relativePath = relativePath.substring(0, relativePath.length() - 5);
return relativePath.replace(File.separatorChar, '.');
} }
void clearBuildErrors(ResourceFile sourceFile) { void clearBuildErrors(ResourceFile sourceFile) {

View file

@ -32,6 +32,7 @@ import ghidra.app.util.headless.HeadlessAnalyzer;
import ghidra.framework.Application; import ghidra.framework.Application;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.classfinder.ClassSearcher; import ghidra.util.classfinder.ClassSearcher;
import utilities.util.FileUtilities;
/** /**
* A utility class for managing script directories and ScriptInfo objects. * A utility class for managing script directories and ScriptInfo objects.
@ -129,19 +130,13 @@ public class GhidraScriptUtil {
* @return the source directory if found, or null if not * @return the source directory if found, or null if not
*/ */
public static ResourceFile findSourceDirectoryContaining(ResourceFile sourceFile) { public static ResourceFile findSourceDirectoryContaining(ResourceFile sourceFile) {
String sourcePath;
try {
sourcePath = sourceFile.getCanonicalPath();
for (ResourceFile sourceDir : getScriptSourceDirectories()) { for (ResourceFile sourceDir : getScriptSourceDirectories()) {
if (sourcePath.startsWith(sourceDir.getCanonicalPath() + File.separatorChar)) { if (FileUtilities.relativizePath(sourceDir, sourceFile) != null) {
return sourceDir; return sourceDir;
} }
} }
}
catch (IOException e) {
Msg.error(GhidraScriptUtil.class, Msg.error(GhidraScriptUtil.class,
"Failed to find script in any script directory: " + sourceFile.toString(), e); "Failed to find script in any script directory: " + sourceFile.toString());
}
return null; return null;
} }

View file

@ -140,6 +140,38 @@ public class FileUtilitiesTest {
assertNull(relative); assertNull(relative);
} }
@Test
public void testRelativizePath_ResourceFiles() {
ResourceFile f1 = new ResourceFile(new File("/a/b"));
ResourceFile f2 = new ResourceFile(new File("/a/b/c"));
String relative = FileUtilities.relativizePath(f1, f2);
assertEquals("c", relative);
}
@Test
public void testRelativizePath_ResourceFiles2() {
ResourceFile f1 = new ResourceFile(new File("/a/b"));
ResourceFile f2 = new ResourceFile(new File("/a/b/c/d"));
String relative = FileUtilities.relativizePath(f1, f2);
assertEquals("c/d", relative);
}
@Test
public void testRelativizePath_ResourceFiles_NotRelated() {
ResourceFile f1 = new ResourceFile(new File("/a/b"));
ResourceFile f2 = new ResourceFile(new File("/c/d"));
String relative = FileUtilities.relativizePath(f1, f2);
assertNull(relative);
}
@Test
public void testRelativizePath_ResourceFiles_Same() {
ResourceFile f1 = new ResourceFile(new File("/a/b"));
ResourceFile f2 = new ResourceFile(new File("/a/b"));
String relative = FileUtilities.relativizePath(f1, f2);
assertNull(relative);
}
private ResourceFile createNestedTempFile(String path) throws Exception { private ResourceFile createNestedTempFile(String path) throws Exception {
String tmpdir = AbstractGenericTest.getTestDirectoryPath(); String tmpdir = AbstractGenericTest.getTestDirectoryPath();

View file

@ -902,6 +902,32 @@ public final class FileUtilities {
return childPath; return childPath;
} }
/**
* Return the relative path string of one resource file in another. If
* no path can be constructed or the files are the same, then null is returned.
*
* Note: unlike {@link #relativizePath(File, File)}, this function does not resolve symbolic links.
*
* <P>For example, given, in this order, two files with these paths
* <code>/a/b</code> and <code>/a/b/c</code>, this method will return 'c'.
*
* @param f1 the parent resource file
* @param f2 the child resource file
* @return the relative path of {@code f2} in {@code f1}
*/
public static String relativizePath(ResourceFile f1, ResourceFile f2) {
StringBuilder sb = new StringBuilder(f2.getName());
f2 = f2.getParentFile();
while (f2 != null) {
if (f1.equals(f2)) {
return sb.toString();
}
sb.insert(0, f2.getName() + File.separator);
f2 = f2.getParentFile();
}
return null;
}
public static boolean exists(URI uri) { public static boolean exists(URI uri) {
String scheme = uri.getScheme(); String scheme = uri.getScheme();