GP-4472 Improved handling of read-only case for headless analyzer and GhidraURL connections.

This commit is contained in:
ghidra1 2024-04-03 09:51:19 -04:00
parent 74e402ef15
commit 66c7e4ad19
3 changed files with 56 additions and 35 deletions

View file

@ -603,9 +603,6 @@ public class HeadlessAnalyzer {
*/
private boolean checkUpdateOptions() {
boolean isImport = !options.runScriptsNoImport;
boolean commitAllowed = isCommitAllowed();
if (options.readOnly) {
String readOnlyError =
"Abort due to Headless analyzer error: The requested -readOnly option " +
@ -621,7 +618,13 @@ public class HeadlessAnalyzer {
return false;
}
}
else if (!isInWritableProject()) {
Msg.error(this, "Processing files within read-only project/repository " +
"- the -readOnly option is required.");
return false;
}
boolean commitAllowed = isCommitAllowed();
if (options.commit && !commitAllowed) {
Msg.error(this,
"Commit to repository not possible (due to permission or connection issue)");
@ -640,6 +643,7 @@ public class HeadlessAnalyzer {
}
if (options.overwrite) {
boolean isImport = !options.runScriptsNoImport;
if (!isImport) {
Msg.info(this,
"Ignoring -overwrite because it is not applicable to -process mode.");
@ -654,6 +658,10 @@ public class HeadlessAnalyzer {
return true;
}
private boolean isInWritableProject() {
return project.getProjectData().getRootFolder().isInWritableProject();
}
private boolean isCommitAllowed() {
RepositoryAdapter repository = project.getRepository();
if (repository == null) {
@ -666,7 +674,7 @@ public class HeadlessAnalyzer {
}
User user = repository.getUser();
if (!user.hasWritePermission()) {
Msg.warn(this, "User '" + user.getName() +
Msg.error(this, "User '" + user.getName() +
"' does not have write permission to repository - commit not allowed");
return false;
}
@ -1126,31 +1134,38 @@ public class HeadlessAnalyzer {
boolean keepFile = true; // if false file should be deleted after release
boolean terminateCheckoutWhenDone = false;
boolean readOnlyFile = options.readOnly || domFile.isReadOnly();
boolean readOnlyFile =
options.readOnly || domFile.isReadOnly() || !domFile.isInWritableProject();
try {
// Exclusive checkout required when commit option specified
if (!readOnlyFile) {
if (domFile.isVersioned()) {
if (!domFile.isCheckedOut()) {
if (!domFile.checkout(options.commit, TaskMonitor.DUMMY)) {
Msg.warn(this, "Skipped processing for " + domFile.getPathname() +
" -- failed to get exclusive file checkout required for commit");
return;
}
}
else if (options.commit && !domFile.isCheckedOutExclusive()) {
Msg.error(this, "Skipped processing for " + domFile.getPathname() +
" -- file is checked-out non-exclusive (commit requires exclusive checkout)");
if (!readOnlyFile && domFile.isVersioned()) {
if (!domFile.isCheckedOut()) {
if (!domFile.canCheckout()) {
Msg.warn(this, "Skipped processing for " + domFile.getPathname() +
" within read-only repository");
return;
}
if (!domFile.checkout(options.commit, TaskMonitor.DUMMY)) {
Msg.warn(this, "Skipped processing for " + domFile.getPathname() +
" -- failed to get exclusive file checkout required for commit");
return;
}
// Only terminate checkout when done if we did the checkout
terminateCheckoutWhenDone = true;
}
else if (options.commit && !domFile.isCheckedOutExclusive()) {
Msg.error(this, "Skipped processing for " + domFile.getPathname() +
" -- file is checked-out non-exclusive (commit requires exclusive checkout)");
return;
}
terminateCheckoutWhenDone = true;
}
program = (Program) domFile.getDomainObject(this, true, false, TaskMonitor.DUMMY);
Msg.info(this, "REPORT: Processing project file: " + domFile.getPathname());
String readOnlyText = readOnlyFile ? "read-only " : "";
Msg.info(this,
"REPORT: Processing " + readOnlyText + "project file: " + domFile.getPathname());
// This method already takes into account whether the user has set the "noanalysis"
// flag or not

View file

@ -65,28 +65,32 @@ public class DefaultGhidraProtocolConnector extends GhidraProtocolConnector {
repositoryServerAdapter =
ClientUtil.getRepositoryServer(url.getHost(), url.getPort(), true);
if (!repositoryServerAdapter.isConnected()) {
if (repositoryServerAdapter.isCancelled()) {
return statusCode;
}
Throwable t = repositoryServerAdapter.getLastConnectError();
if (t instanceof LoginException) {
statusCode = StatusCode.UNAUTHORIZED;
}
return statusCode;
}
if (repositoryName == null) {
if (repositoryServerAdapter.isReadOnly()) {
this.readOnly = true; // write access not permitted
Msg.warn(this, "User does not have write permission for server");
}
statusCode = StatusCode.OK;
return statusCode;
}
repositoryAdapter = repositoryServerAdapter.getRepository(repositoryName);
if (repositoryServerAdapter.isConnected()) {
try {
repositoryAdapter.connect();
}
catch (RepositoryNotFoundException e) {
statusCode = StatusCode.NOT_FOUND;
return statusCode;
}
try {
repositoryAdapter.connect();
}
else if (!repositoryServerAdapter.isCancelled()) {
Throwable t = repositoryServerAdapter.getLastConnectError();
if (t instanceof LoginException) {
statusCode = StatusCode.UNAUTHORIZED;
}
//throw new NotConnectedException("Not connected to repository server", t);
catch (RepositoryNotFoundException e) {
statusCode = StatusCode.NOT_FOUND;
return statusCode;
}

View file

@ -415,8 +415,10 @@ The Headless Analyzer uses the command-line parameters discussed below. See <a h
<a name="readOnly"><typewriter>-readOnly</typewriter></a><br>
If present in <typewriter>-import</typewriter> mode, imported files will NOT be saved to the
project. If present in <typewriter>-process</typewriter> mode, any changes made to existing
files by scripts or analysis are discarded. The <typewriter>-overwrite</typewriter> option
will be ignored if this option is specified during import operations.
files by scripts or analysis are discarded. When processing a shared project or URL associated
with a read-only repository, such files will be skipped unless this option is specified.
The <typewriter>-overwrite</typewriter> option will be ignored if this option is specified
during import operations.
</LI>
<br><br>