mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-08 18:26:01 +02:00
[429271] Fix for special characters in directory names (master branch)
Change-Id: Ib5ff490ec83dd4791cb01f6d1f85f5b0db189f77 Signed-off-by: Greg Watson <g.watson@computer.org>
This commit is contained in:
parent
28c493cbe7
commit
3faf39df8d
4 changed files with 130 additions and 129 deletions
|
@ -12,7 +12,9 @@
|
||||||
package org.eclipse.remote.internal.jsch.core.commands;
|
package org.eclipse.remote.internal.jsch.core.commands;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.text.CharacterIterator;
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
|
import java.text.StringCharacterIterator;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
|
@ -109,6 +111,78 @@ public abstract class AbstractRemoteCommand<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract class ExecCallable<T1> implements Callable<T1> {
|
||||||
|
private IProgressMonitor fProgressMonitor;
|
||||||
|
private ChannelExec fExecChannel;
|
||||||
|
|
||||||
|
private Future<T1> asyncCmdInThread() throws RemoteConnectionException {
|
||||||
|
setChannel(fConnection.getExecChannel());
|
||||||
|
return fPool.submit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see java.util.concurrent.Callable#call()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public abstract T1 call() throws JSchException, IOException;
|
||||||
|
|
||||||
|
private void finalizeCmdInThread() {
|
||||||
|
setChannel(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChannelExec getChannel() {
|
||||||
|
return fExecChannel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IProgressMonitor getProgressMonitor() {
|
||||||
|
return fProgressMonitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function opens exec channel and then executes the exec operation. If
|
||||||
|
* run on the main thread it executes it on a separate thread
|
||||||
|
*/
|
||||||
|
public T1 getResult(IProgressMonitor monitor) throws RemoteConnectionException {
|
||||||
|
Future<T1> future = null;
|
||||||
|
fProgressMonitor = SubMonitor.convert(monitor, 10);
|
||||||
|
try {
|
||||||
|
future = asyncCmdInThread();
|
||||||
|
return waitCmdInThread(future);
|
||||||
|
} finally {
|
||||||
|
finalizeCmdInThread();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChannel(ChannelExec channel) {
|
||||||
|
fExecChannel = channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private T1 waitCmdInThread(Future<T1> future) throws RemoteConnectionException {
|
||||||
|
boolean bInterrupted = Thread.interrupted();
|
||||||
|
while (!getProgressMonitor().isCanceled()) {
|
||||||
|
try {
|
||||||
|
return future.get(100, TimeUnit.MILLISECONDS);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
bInterrupted = true;
|
||||||
|
} catch (TimeoutException e) {
|
||||||
|
// ignore
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
getChannel().disconnect();
|
||||||
|
throw new RemoteConnectionException(e.getMessage());
|
||||||
|
}
|
||||||
|
getProgressMonitor().worked(1);
|
||||||
|
}
|
||||||
|
if (bInterrupted) {
|
||||||
|
Thread.currentThread().interrupt(); // set current thread flag
|
||||||
|
}
|
||||||
|
future.cancel(true);
|
||||||
|
getChannel().disconnect();
|
||||||
|
throw new RemoteConnectionException(Messages.AbstractRemoteCommand_Operation_cancelled_by_user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected abstract class SftpCallable<T1> implements Callable<T1> {
|
protected abstract class SftpCallable<T1> implements Callable<T1> {
|
||||||
private IProgressMonitor fProgressMonitor;
|
private IProgressMonitor fProgressMonitor;
|
||||||
private ChannelSftp fSftpChannel;
|
private ChannelSftp fSftpChannel;
|
||||||
|
@ -184,78 +258,6 @@ public abstract class AbstractRemoteCommand<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract class ExecCallable<T1> implements Callable<T1> {
|
|
||||||
private IProgressMonitor fProgressMonitor;
|
|
||||||
private ChannelExec fExecChannel;
|
|
||||||
|
|
||||||
private Future<T1> asyncCmdInThread() throws RemoteConnectionException {
|
|
||||||
setChannel(fConnection.getExecChannel());
|
|
||||||
return fPool.submit(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see java.util.concurrent.Callable#call()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public abstract T1 call() throws JSchException, IOException;
|
|
||||||
|
|
||||||
private void finalizeCmdInThread() {
|
|
||||||
setChannel(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChannelExec getChannel() {
|
|
||||||
return fExecChannel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IProgressMonitor getProgressMonitor() {
|
|
||||||
return fProgressMonitor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function opens exec channel and then executes the exec operation. If
|
|
||||||
* run on the main thread it executes it on a separate thread
|
|
||||||
*/
|
|
||||||
public T1 getResult(IProgressMonitor monitor) throws RemoteConnectionException {
|
|
||||||
Future<T1> future = null;
|
|
||||||
fProgressMonitor = SubMonitor.convert(monitor, 10);
|
|
||||||
try {
|
|
||||||
future = asyncCmdInThread();
|
|
||||||
return waitCmdInThread(future);
|
|
||||||
} finally {
|
|
||||||
finalizeCmdInThread();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setChannel(ChannelExec channel) {
|
|
||||||
fExecChannel = channel;
|
|
||||||
}
|
|
||||||
|
|
||||||
private T1 waitCmdInThread(Future<T1> future) throws RemoteConnectionException {
|
|
||||||
boolean bInterrupted = Thread.interrupted();
|
|
||||||
while (!getProgressMonitor().isCanceled()) {
|
|
||||||
try {
|
|
||||||
return future.get(100, TimeUnit.MILLISECONDS);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
bInterrupted = true;
|
|
||||||
} catch (TimeoutException e) {
|
|
||||||
// ignore
|
|
||||||
} catch (ExecutionException e) {
|
|
||||||
getChannel().disconnect();
|
|
||||||
throw new RemoteConnectionException(e.getMessage());
|
|
||||||
}
|
|
||||||
getProgressMonitor().worked(1);
|
|
||||||
}
|
|
||||||
if (bInterrupted) {
|
|
||||||
Thread.currentThread().interrupt(); // set current thread flag
|
|
||||||
}
|
|
||||||
future.cancel(true);
|
|
||||||
getChannel().disconnect();
|
|
||||||
throw new RemoteConnectionException(Messages.AbstractRemoteCommand_Operation_cancelled_by_user);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ExecutorService fPool = Executors.newSingleThreadExecutor();
|
private static ExecutorService fPool = Executors.newSingleThreadExecutor();
|
||||||
|
|
||||||
private final JSchConnection fConnection;
|
private final JSchConnection fConnection;
|
||||||
|
@ -347,6 +349,10 @@ public abstract class AbstractRemoteCommand<T> {
|
||||||
return fileInfo;
|
return fileInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JSchConnection getConnection() {
|
||||||
|
return fConnection;
|
||||||
|
}
|
||||||
|
|
||||||
public int getFinishStatus() {
|
public int getFinishStatus() {
|
||||||
int code = 0;
|
int code = 0;
|
||||||
|
|
||||||
|
@ -429,7 +435,53 @@ public abstract class AbstractRemoteCommand<T> {
|
||||||
|
|
||||||
protected abstract T getResult(IProgressMonitor monitor) throws RemoteConnectionException;
|
protected abstract T getResult(IProgressMonitor monitor) throws RemoteConnectionException;
|
||||||
|
|
||||||
public JSchConnection getConnection() {
|
protected String quote(String path, boolean full) {
|
||||||
return fConnection;
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
StringCharacterIterator iter = new StringCharacterIterator(path);
|
||||||
|
for (char c = iter.first(); c != CharacterIterator.DONE; c = iter.next()) {
|
||||||
|
switch (c) {
|
||||||
|
case '(':
|
||||||
|
case ')':
|
||||||
|
case '[':
|
||||||
|
case ']':
|
||||||
|
case '{':
|
||||||
|
case '}':
|
||||||
|
case '|':
|
||||||
|
case '\\':
|
||||||
|
case '*':
|
||||||
|
case '&':
|
||||||
|
case '^':
|
||||||
|
case '%':
|
||||||
|
case '$':
|
||||||
|
case '#':
|
||||||
|
case '@':
|
||||||
|
case '!':
|
||||||
|
case '~':
|
||||||
|
case '`':
|
||||||
|
case '\'':
|
||||||
|
case '"':
|
||||||
|
case ':':
|
||||||
|
case ';':
|
||||||
|
case '?':
|
||||||
|
case '<':
|
||||||
|
case '>':
|
||||||
|
case ',':
|
||||||
|
case '\n':
|
||||||
|
if (full) {
|
||||||
|
buffer.append('\\');
|
||||||
|
}
|
||||||
|
buffer.append(c);
|
||||||
|
continue;
|
||||||
|
case ' ':
|
||||||
|
buffer.append('\\');
|
||||||
|
buffer.append(c);
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
buffer.append(c);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buffer.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -55,7 +55,7 @@ public class ChildInfosCommand extends AbstractRemoteCommand<IFileInfo[]> {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public Vector<LsEntry> call() throws JSchException, SftpException {
|
public Vector<LsEntry> call() throws JSchException, SftpException {
|
||||||
return getChannel().ls(fRemotePath.toString());
|
return getChannel().ls(quote(fRemotePath.toString(), true));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
package org.eclipse.remote.internal.jsch.core.commands;
|
package org.eclipse.remote.internal.jsch.core.commands;
|
||||||
|
|
||||||
import java.text.CharacterIterator;
|
|
||||||
import java.text.StringCharacterIterator;
|
|
||||||
|
|
||||||
import org.eclipse.core.runtime.IPath;
|
import org.eclipse.core.runtime.IPath;
|
||||||
import org.eclipse.core.runtime.IProgressMonitor;
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
import org.eclipse.core.runtime.SubMonitor;
|
import org.eclipse.core.runtime.SubMonitor;
|
||||||
|
@ -30,53 +27,4 @@ public class DeleteCommand extends AbstractRemoteCommand<Void> {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String quote(String path, boolean full) {
|
|
||||||
StringBuffer buffer = new StringBuffer();
|
|
||||||
StringCharacterIterator iter = new StringCharacterIterator(path);
|
|
||||||
for (char c = iter.first(); c != CharacterIterator.DONE; c = iter.next()) {
|
|
||||||
switch (c) {
|
|
||||||
case '(':
|
|
||||||
case ')':
|
|
||||||
case '[':
|
|
||||||
case ']':
|
|
||||||
case '{':
|
|
||||||
case '}':
|
|
||||||
case '|':
|
|
||||||
case '\\':
|
|
||||||
case '*':
|
|
||||||
case '&':
|
|
||||||
case '^':
|
|
||||||
case '%':
|
|
||||||
case '$':
|
|
||||||
case '#':
|
|
||||||
case '@':
|
|
||||||
case '!':
|
|
||||||
case '~':
|
|
||||||
case '`':
|
|
||||||
case '\'':
|
|
||||||
case '"':
|
|
||||||
case ':':
|
|
||||||
case ';':
|
|
||||||
case '?':
|
|
||||||
case '<':
|
|
||||||
case '>':
|
|
||||||
case ',':
|
|
||||||
case '\n':
|
|
||||||
if (full) {
|
|
||||||
buffer.append('\\');
|
|
||||||
}
|
|
||||||
buffer.append(c);
|
|
||||||
continue;
|
|
||||||
case ' ':
|
|
||||||
buffer.append('\\');
|
|
||||||
buffer.append(c);
|
|
||||||
continue;
|
|
||||||
default:
|
|
||||||
buffer.append(c);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return buffer.toString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,15 +38,16 @@ public class PutInfoCommand extends AbstractRemoteCommand<Void> {
|
||||||
final SubMonitor subMon = SubMonitor.convert(monitor, 30);
|
final SubMonitor subMon = SubMonitor.convert(monitor, 30);
|
||||||
|
|
||||||
FetchInfoCommand command = new FetchInfoCommand(getConnection(), fRemotePath);
|
FetchInfoCommand command = new FetchInfoCommand(getConnection(), fRemotePath);
|
||||||
|
String quotedPath = quote(fRemotePath.toString(), true);
|
||||||
if ((fOptions & EFS.SET_ATTRIBUTES) != 0) {
|
if ((fOptions & EFS.SET_ATTRIBUTES) != 0) {
|
||||||
chmod(getPermissions(fFileInfo), fRemotePath.toString(), subMon.newChild(10));
|
chmod(getPermissions(fFileInfo), quotedPath, subMon.newChild(10));
|
||||||
}
|
}
|
||||||
if ((fOptions & EFS.SET_LAST_MODIFIED) != 0) {
|
if ((fOptions & EFS.SET_LAST_MODIFIED) != 0) {
|
||||||
IFileInfo info = command.getResult(subMon.newChild(10));
|
IFileInfo info = command.getResult(subMon.newChild(10));
|
||||||
long oldMTime = info.getLastModified();
|
long oldMTime = info.getLastModified();
|
||||||
int newMTime = (int) (oldMTime / 1000);
|
int newMTime = (int) (oldMTime / 1000);
|
||||||
if (oldMTime != newMTime) {
|
if (oldMTime != newMTime) {
|
||||||
setMTime(newMTime, fRemotePath.toString(), subMon.newChild(10));
|
setMTime(newMTime, quotedPath, subMon.newChild(10));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
Loading…
Add table
Reference in a new issue