mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-12 19:45:22 +02:00
[213438] Checked in initial scp filesubsystem contribution by Nikita Shulga (Mentor Graphics).
This commit is contained in:
parent
b2ff1be03f
commit
1a03a16e19
17 changed files with 1339 additions and 0 deletions
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||||
|
<classpathentry kind="src" path="src"/>
|
||||||
|
<classpathentry kind="output" path="bin"/>
|
||||||
|
</classpath>
|
28
rse/plugins/org.eclipse.rse.subsystems.files.scp/.project
Normal file
28
rse/plugins/org.eclipse.rse.subsystems.files.scp/.project
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>org.eclipse.rse.subsystems.files.scp</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.pde.PluginNature</nature>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
|
@ -0,0 +1,7 @@
|
||||||
|
#Fri Feb 06 22:40:19 JST 2009
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
|
||||||
|
org.eclipse.jdt.core.compiler.compliance=1.5
|
||||||
|
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||||
|
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||||
|
org.eclipse.jdt.core.compiler.source=1.5
|
|
@ -0,0 +1,19 @@
|
||||||
|
Manifest-Version: 1.0
|
||||||
|
Bundle-ManifestVersion: 2
|
||||||
|
Bundle-Name: %pluginName
|
||||||
|
Bundle-SymbolicName: org.eclipse.rse.subsystems.files.scp;singleton:=true
|
||||||
|
Bundle-Version: 0.1.0.qualifier
|
||||||
|
Bundle-Vendor: %providerName
|
||||||
|
Bundle-Localization: plugin
|
||||||
|
Bundle-RequiredExecutionEnvironment: J2SE-1.5
|
||||||
|
Require-Bundle: org.eclipse.rse.subsystems.files.core;bundle-version="[3.0.0,4.0.0)",
|
||||||
|
org.eclipse.rse.services.ssh;bundle-version="[3.0.0,3.1.0)",
|
||||||
|
org.eclipse.rse.connectorservice.ssh;bundle-version="[2.0.0,2.2.0)",
|
||||||
|
org.eclipse.rse.services;bundle-version="[3.0.0,4.0.0)",
|
||||||
|
org.eclipse.rse.core;bundle-version="[3.0.0,4.0.0)",
|
||||||
|
org.eclipse.rse.ui;bundle-version="[3.0.0,4.0.0)",
|
||||||
|
com.jcraft.jsch;bundle-version="[0.1.31,1.0.0)",
|
||||||
|
org.eclipse.core.runtime;bundle-version="[3.4.0,3.7.0)"
|
||||||
|
Bundle-Activator: org.eclipse.rse.internal.subsystems.files.scp.Activator
|
||||||
|
Export-Package: org.eclipse.rse.internal.subsystems.files.scp;x-internal:=true,
|
||||||
|
org.eclipse.rse.subsystems.files.scp
|
28
rse/plugins/org.eclipse.rse.subsystems.files.scp/about.html
Normal file
28
rse/plugins/org.eclipse.rse.subsystems.files.scp/about.html
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
|
||||||
|
<title>About</title>
|
||||||
|
</head>
|
||||||
|
<body lang="EN-US">
|
||||||
|
<h2>About This Content</h2>
|
||||||
|
|
||||||
|
<p>June 5, 2007</p>
|
||||||
|
<h3>License</h3>
|
||||||
|
|
||||||
|
<p>The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise
|
||||||
|
indicated below, the Content is provided to you under the terms and conditions of the
|
||||||
|
Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available
|
||||||
|
at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
|
||||||
|
For purposes of the EPL, "Program" will mean the Content.</p>
|
||||||
|
|
||||||
|
<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
|
||||||
|
being redistributed by another party ("Redistributor") and different terms and conditions may
|
||||||
|
apply to your use of any object code in the Content. Check the Redistributor's license that was
|
||||||
|
provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
|
||||||
|
indicated below, the terms and conditions of the EPL still apply to any source code in the Content
|
||||||
|
and such source code may be obtained at <a href="http://www.eclipse.org">http://www.eclipse.org</a>.</p>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,6 @@
|
||||||
|
source.. = src/
|
||||||
|
output.. = bin/
|
||||||
|
bin.includes = META-INF/,\
|
||||||
|
icons/,\
|
||||||
|
plugin.properties,\
|
||||||
|
plugin.xml
|
Binary file not shown.
After Width: | Height: | Size: 157 B |
Binary file not shown.
After Width: | Height: | Size: 224 B |
|
@ -0,0 +1,16 @@
|
||||||
|
################################################################################
|
||||||
|
# Copyright (c) 2010 Mentor Graphics Corporation and others.
|
||||||
|
# All rights reserved. This program and the accompanying materials
|
||||||
|
# are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
# which accompanies this distribution, and is available at
|
||||||
|
# http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
#
|
||||||
|
# Contributors:
|
||||||
|
# Nikita Shulga - initial API and implementation
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
pluginName = RSE SCP Files (Incubation)
|
||||||
|
providerName = Eclipse.org - DSDP
|
||||||
|
|
||||||
|
ScpFileSubsystemName=Scp Files
|
||||||
|
ScpFileSubsystemDescription=Work with files on remote systems using the Secure Shell (ssh) protocol.
|
32
rse/plugins/org.eclipse.rse.subsystems.files.scp/plugin.xml
Normal file
32
rse/plugins/org.eclipse.rse.subsystems.files.scp/plugin.xml
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
Copyright (c) 2009, 2010 Mentor Graphics Corporation and others.
|
||||||
|
All rights reserved. This program and the accompanying materials
|
||||||
|
are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
which accompanies this distribution, and is available at
|
||||||
|
http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
|
||||||
|
Contributors:
|
||||||
|
Nikita Shulga - initial API and implementation
|
||||||
|
-->
|
||||||
|
|
||||||
|
<?eclipse version="3.1"?>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<extension
|
||||||
|
point="org.eclipse.rse.core.subsystemConfigurations">
|
||||||
|
<configuration
|
||||||
|
category="files"
|
||||||
|
class="org.eclipse.rse.subsystems.files.scp.ScpFileSubSystemConfiguration"
|
||||||
|
description="%ScpFileSubsystemName"
|
||||||
|
icon="icons/full/obj16/systemfiles_obj.gif"
|
||||||
|
iconlive="icons/full/obj16/systemfileslive_obj.gif"
|
||||||
|
id="scp.files"
|
||||||
|
name="%ScpFileSubsystemName"
|
||||||
|
priority="80"
|
||||||
|
serviceType="_scp-ssh._tcp"
|
||||||
|
systemTypeIds="org.eclipse.rse.systemtype.linux;org.eclipse.rse.systemtype.unix;org.eclipse.rse.systemtype.aix;org.eclipse.rse.systemtype.ssh"
|
||||||
|
vendor="%providerName">
|
||||||
|
</configuration>
|
||||||
|
</extension>
|
||||||
|
</plugin>
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2009, 2010 Mentor Graphics Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Nikita Shulga (Mentor Graphics) - initial implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.rse.internal.subsystems.files.scp;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.core.runtime.Platform;
|
||||||
|
import org.eclipse.core.runtime.Plugin;
|
||||||
|
import org.eclipse.core.runtime.Status;
|
||||||
|
import org.osgi.framework.Bundle;
|
||||||
|
import org.osgi.framework.BundleContext;
|
||||||
|
|
||||||
|
public class Activator extends Plugin {
|
||||||
|
|
||||||
|
// The plug-in ID
|
||||||
|
public static final String PLUGIN_ID = Activator.class.getCanonicalName();
|
||||||
|
|
||||||
|
private static Activator plugin = null;
|
||||||
|
private static Bundle bundle = null;
|
||||||
|
|
||||||
|
public Activator() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Plugin getDefault() {
|
||||||
|
return plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bundle getDefaultBundle() {
|
||||||
|
return bundle;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start(BundleContext context) throws Exception {
|
||||||
|
super.start(context);
|
||||||
|
plugin = this;
|
||||||
|
bundle = context.getBundle();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop(BundleContext context) throws Exception {
|
||||||
|
plugin = null;
|
||||||
|
bundle = null;
|
||||||
|
super.stop(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void log(String msg) {
|
||||||
|
log(msg, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void log(String msg, Exception e) {
|
||||||
|
log(IStatus.INFO, msg, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void warn(String msg, Exception e) {
|
||||||
|
log(IStatus.WARNING, msg, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void log(int sev, String msg, Exception e) {
|
||||||
|
Platform.getLog(getDefaultBundle()).log(
|
||||||
|
new Status(sev, PLUGIN_ID, msg, e));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2006, 2010 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Initial Contributors:
|
||||||
|
* The following IBM employees contributed to the Remote System Explorer
|
||||||
|
* component that contains this file: David McKnight, Kushal Munir,
|
||||||
|
* Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson,
|
||||||
|
* Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Martin Oberhuber (Wind River) - Adapted from FTPFileAdapter.
|
||||||
|
* Martin Oberhuber (Wind River) - [235363][api][breaking] IHostFileToRemoteFileAdapter methods should return AbstractRemoteFile
|
||||||
|
* Nikita Shulga (Mentor Graphics) - Adapted from SftpFileAdapter.
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.rse.internal.subsystems.files.scp;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.rse.services.files.IHostFile;
|
||||||
|
import org.eclipse.rse.subsystems.files.core.servicesubsystem.AbstractRemoteFile;
|
||||||
|
import org.eclipse.rse.subsystems.files.core.servicesubsystem.FileServiceSubSystem;
|
||||||
|
import org.eclipse.rse.subsystems.files.core.subsystems.IHostFileToRemoteFileAdapter;
|
||||||
|
import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFile;
|
||||||
|
import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFileContext;
|
||||||
|
|
||||||
|
public class ScpFileAdapter implements IHostFileToRemoteFileAdapter {
|
||||||
|
|
||||||
|
public AbstractRemoteFile convertToRemoteFile(FileServiceSubSystem ss,
|
||||||
|
IRemoteFileContext context, IRemoteFile parent, IHostFile node) {
|
||||||
|
|
||||||
|
ScpRemoteFile file = new ScpRemoteFile(ss, context, parent, node);
|
||||||
|
ss.cacheRemoteFile(file);
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AbstractRemoteFile[] convertToRemoteFiles(FileServiceSubSystem ss,
|
||||||
|
IRemoteFileContext context, IRemoteFile parent, IHostFile[] nodes) {
|
||||||
|
|
||||||
|
if (nodes == null)
|
||||||
|
return new AbstractRemoteFile[0];
|
||||||
|
|
||||||
|
List<ScpRemoteFile> results = new ArrayList<ScpRemoteFile>();
|
||||||
|
for (IHostFile node : nodes) {
|
||||||
|
ScpRemoteFile file = new ScpRemoteFile(ss, context, parent, node);
|
||||||
|
ss.cacheRemoteFile(file);
|
||||||
|
results.add(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ScpRemoteFile[]) results.toArray(new ScpRemoteFile[results
|
||||||
|
.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,248 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2009, 2010 Mentor Graphics Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Nikita Shulga - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.rse.internal.subsystems.files.scp;
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Stack;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.eclipse.rse.services.clientserver.messages.SystemMessageException;
|
||||||
|
import org.eclipse.rse.services.files.HostFilePermissions;
|
||||||
|
import org.eclipse.rse.services.files.IHostFilePermissions;
|
||||||
|
|
||||||
|
import com.jcraft.jsch.Session;
|
||||||
|
|
||||||
|
public class ScpFileAttr {
|
||||||
|
private String lsString;
|
||||||
|
private String attrString = null;
|
||||||
|
private int linkNo = 0;
|
||||||
|
private long mTime = 0;
|
||||||
|
private String user = null;
|
||||||
|
private String group = null;
|
||||||
|
private long size = -1;
|
||||||
|
private String name = null;
|
||||||
|
private String linkName = null;
|
||||||
|
|
||||||
|
public IHostFilePermissions getFilePermissions() {
|
||||||
|
return new HostFilePermissions(getAttrs(), getUser(), getGroup());
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getMTime() {
|
||||||
|
if (!initialized)
|
||||||
|
doSplit();
|
||||||
|
return mTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getSize() {
|
||||||
|
if (!initialized)
|
||||||
|
doSplit();
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUser() {
|
||||||
|
if (!initialized)
|
||||||
|
doSplit();
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGroup() {
|
||||||
|
if (!initialized)
|
||||||
|
doSplit();
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLinkNo() {
|
||||||
|
if (!initialized)
|
||||||
|
doSplit();
|
||||||
|
return linkNo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
if (!initialized)
|
||||||
|
doSplit();
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLinkName() {
|
||||||
|
if (!initialized)
|
||||||
|
doSplit();
|
||||||
|
return linkName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAttrs() {
|
||||||
|
if (!initialized)
|
||||||
|
doSplit();
|
||||||
|
|
||||||
|
if (attrString == null || attrString.length() < 9)
|
||||||
|
return "---------"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
return attrString;
|
||||||
|
}
|
||||||
|
|
||||||
|
private char getFileType() {
|
||||||
|
String attrs = getAttrs();
|
||||||
|
if (attrs == null || attrs.length() == 0)
|
||||||
|
return 0;
|
||||||
|
return attrs.charAt(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isBlockDevice() {
|
||||||
|
return getFileType() == 'b';
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCharDevice() {
|
||||||
|
return getFileType() == 'c';
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLink() {
|
||||||
|
return getFileType() == 'l';
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDirectory() {
|
||||||
|
return getFileType() == 'd';
|
||||||
|
}
|
||||||
|
|
||||||
|
ScpFileAttr(String str) {
|
||||||
|
lsString = str;
|
||||||
|
if (lsString.endsWith("\n")) //$NON-NLS-1$
|
||||||
|
lsString = lsString.substring(0, lsString.length() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean initialized = false;
|
||||||
|
|
||||||
|
private void doSplit() {
|
||||||
|
if (initialized)
|
||||||
|
return;
|
||||||
|
initialized = true;
|
||||||
|
try {
|
||||||
|
SplitAux();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Activator.warn(
|
||||||
|
"ScpFileAttr:Exception occured while splitting string "
|
||||||
|
+ lsString, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ls command uses two short date formats: - for files modified more than 6
|
||||||
|
* month ago - for files modified less than 6 month ago
|
||||||
|
*/
|
||||||
|
final static DateFormat lessThanSixMonthOldFormat = new SimpleDateFormat(
|
||||||
|
"MMM dd HH:mm"); //$NON-NLS-1$
|
||||||
|
final static DateFormat moreThanSixMonthOldFormat = new SimpleDateFormat(
|
||||||
|
"MMM dd yyyy"); //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses date time string returned by ls command
|
||||||
|
*
|
||||||
|
* @param date
|
||||||
|
* - file modification date as string
|
||||||
|
* @return time in seconds since start of epoch until mTime
|
||||||
|
*/
|
||||||
|
static long parseDateTime(String date) {
|
||||||
|
// TODO: Add support for ls -le date format
|
||||||
|
try {
|
||||||
|
Date d = lessThanSixMonthOldFormat.parse(date);
|
||||||
|
Calendar c = Calendar.getInstance();
|
||||||
|
c.setTime(d);
|
||||||
|
c.set(Calendar.YEAR, Calendar.getInstance().get(Calendar.YEAR));
|
||||||
|
return c.getTimeInMillis() / 1000;
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Date d = moreThanSixMonthOldFormat.parse(date);
|
||||||
|
return d.getTime() / 1000;
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Pattern lsPattern = Pattern.compile("\\s+"); //$NON-NLS-1$
|
||||||
|
|
||||||
|
public void SplitAux() throws Exception {
|
||||||
|
Stack<String> fields = new Stack<String>();
|
||||||
|
for (String s : lsPattern.split(lsString))
|
||||||
|
fields.insertElementAt(s, 0);
|
||||||
|
|
||||||
|
/* store file attributes */
|
||||||
|
if (fields.empty())
|
||||||
|
return;
|
||||||
|
attrString = fields.pop();
|
||||||
|
|
||||||
|
/* store link number */
|
||||||
|
if (fields.empty())
|
||||||
|
return;
|
||||||
|
linkNo = Integer.parseInt(fields.pop());
|
||||||
|
|
||||||
|
/* store uid and gid */
|
||||||
|
if (fields.empty())
|
||||||
|
return;
|
||||||
|
user = fields.pop();
|
||||||
|
if (fields.empty())
|
||||||
|
return;
|
||||||
|
group = fields.pop();
|
||||||
|
|
||||||
|
/* store file size */
|
||||||
|
if (fields.empty())
|
||||||
|
return;
|
||||||
|
if (!isCharDevice() && !isBlockDevice())
|
||||||
|
size = Long.parseLong(fields.pop());
|
||||||
|
else {
|
||||||
|
/* Size is undefined for character and block devices */
|
||||||
|
size = 0;
|
||||||
|
/* And we don't know what to do with devs major/minor */
|
||||||
|
fields.pop();
|
||||||
|
if (fields.empty())
|
||||||
|
return;
|
||||||
|
fields.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Date always takes three fields */
|
||||||
|
if (fields.empty())
|
||||||
|
return;
|
||||||
|
String dateField = fields.pop();
|
||||||
|
if (fields.empty())
|
||||||
|
return;
|
||||||
|
dateField = dateField + " " + fields.pop(); //$NON-NLS-1$
|
||||||
|
if (fields.empty())
|
||||||
|
return;
|
||||||
|
dateField = dateField + " " + fields.pop(); //$NON-NLS-1$
|
||||||
|
|
||||||
|
mTime = parseDateTime(dateField);
|
||||||
|
/* The rest of the entry is name ( and may be symlink ) */
|
||||||
|
String[] namesplit = Pattern.compile(
|
||||||
|
dateField.replace(" ", "\\s+") + "\\s").split(lsString); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
|
||||||
|
if (namesplit.length != 2)
|
||||||
|
return;
|
||||||
|
name = namesplit[1];
|
||||||
|
if (isLink()) {
|
||||||
|
namesplit = name.split(" -> "); //$NON-NLS-1$
|
||||||
|
if (namesplit.length != 2)
|
||||||
|
return;
|
||||||
|
name = namesplit[0];
|
||||||
|
linkName = namesplit[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ScpFileAttr getAttr(Session sess, String path)
|
||||||
|
throws SystemMessageException {
|
||||||
|
String attr = ScpFileUtils.execCommandSafe(sess, "ls -land " //$NON-NLS-1$
|
||||||
|
+ ScpFileUtils.escapePath(path));
|
||||||
|
if (attr == null || attr.length() < 9)
|
||||||
|
return null;
|
||||||
|
return new ScpFileAttr(attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,522 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2009, 2010 Mentor Graphics Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Nikita Shulga - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.rse.internal.subsystems.files.scp;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.rse.internal.services.ssh.ISshSessionProvider;
|
||||||
|
import org.eclipse.rse.internal.services.ssh.files.SftpHostFile;
|
||||||
|
import org.eclipse.rse.services.clientserver.FileTypeMatcher;
|
||||||
|
import org.eclipse.rse.services.clientserver.IMatcher;
|
||||||
|
import org.eclipse.rse.services.clientserver.NamePatternMatcher;
|
||||||
|
import org.eclipse.rse.services.clientserver.messages.SimpleSystemMessage;
|
||||||
|
import org.eclipse.rse.services.clientserver.messages.SystemMessageException;
|
||||||
|
import org.eclipse.rse.services.files.AbstractFileService;
|
||||||
|
import org.eclipse.rse.services.files.HostFilePermissions;
|
||||||
|
import org.eclipse.rse.services.files.IFilePermissionsService;
|
||||||
|
import org.eclipse.rse.services.files.IHostFile;
|
||||||
|
import org.eclipse.rse.services.files.IHostFilePermissions;
|
||||||
|
import org.eclipse.rse.services.files.IHostFilePermissionsContainer;
|
||||||
|
|
||||||
|
import com.jcraft.jsch.ChannelExec;
|
||||||
|
import com.jcraft.jsch.Session;
|
||||||
|
|
||||||
|
@SuppressWarnings("restriction")
|
||||||
|
public class ScpFileService extends AbstractFileService implements
|
||||||
|
IFilePermissionsService {
|
||||||
|
|
||||||
|
private final ISshSessionProvider fSessionProvider;
|
||||||
|
private String fUserHome = null;
|
||||||
|
|
||||||
|
public ISshSessionProvider getSessionProvider() {
|
||||||
|
return fSessionProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Session getSession() {
|
||||||
|
return getSessionProvider().getSession();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScpFileService(ISshSessionProvider provider) {
|
||||||
|
fSessionProvider = provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static void throwSystemException(String msg)
|
||||||
|
throws SystemMessageException {
|
||||||
|
throw new SystemMessageException(new SimpleSystemMessage(
|
||||||
|
Activator.PLUGIN_ID, IStatus.ERROR, msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static void throwSystemException(Exception e)
|
||||||
|
throws SystemMessageException {
|
||||||
|
Activator.warn("ScpFileServie.throwSystemExcpeption", e);
|
||||||
|
|
||||||
|
if (e instanceof SystemMessageException)
|
||||||
|
throw (SystemMessageException) e;
|
||||||
|
throw new SystemMessageException(new SimpleSystemMessage(
|
||||||
|
Activator.PLUGIN_ID, IStatus.ERROR, e.getMessage(), e));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected IHostFile[] internalFetch(String parentPath, String fileFilter,
|
||||||
|
int fileType, IProgressMonitor monitor)
|
||||||
|
throws SystemMessageException {
|
||||||
|
|
||||||
|
if (fileFilter == null)
|
||||||
|
fileFilter = "*";
|
||||||
|
IMatcher filematcher = null;
|
||||||
|
if (fileFilter.endsWith(",")) { //$NON-NLS-1$
|
||||||
|
String[] types = fileFilter.split(","); //$NON-NLS-1$
|
||||||
|
filematcher = new FileTypeMatcher(types, true);
|
||||||
|
} else {
|
||||||
|
filematcher = new NamePatternMatcher(fileFilter, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<IHostFile> results = new ArrayList<IHostFile>();
|
||||||
|
Session sess = getSession();
|
||||||
|
String cmd = "ls -lAn " + ScpFileUtils.escapePath(parentPath); //$NON-NLS-1$
|
||||||
|
|
||||||
|
String rc = ScpFileUtils.execCommandSafe(sess, cmd);
|
||||||
|
|
||||||
|
for (String lsString : rc.split(ScpFileUtils.EOL_STRING)) {
|
||||||
|
if (lsString.length() == 0 || lsString.startsWith("total")) //$NON-NLS-1$
|
||||||
|
continue;
|
||||||
|
ScpFileAttr attr = new ScpFileAttr(lsString);
|
||||||
|
if (attr == null || attr.getName() == null) {
|
||||||
|
Activator.warn("internalFetch(parentPath='" + parentPath
|
||||||
|
+ "'): Can't get name of " + lsString, null);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!filematcher.matches(attr.getName()))
|
||||||
|
continue;
|
||||||
|
IHostFile f = makeHostFile(parentPath, null, attr);
|
||||||
|
if (isRightType(fileType, f))
|
||||||
|
results.add(f);
|
||||||
|
}
|
||||||
|
return (IHostFile[]) results.toArray(new IHostFile[results.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCapabilities(IHostFile host) {
|
||||||
|
return IFilePermissionsService.FS_CAN_GET_ALL
|
||||||
|
| IFilePermissionsService.FS_CAN_SET_ALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IHostFilePermissions getFilePermissions(IHostFile file,
|
||||||
|
IProgressMonitor monitor) throws SystemMessageException {
|
||||||
|
if (file instanceof IHostFilePermissionsContainer) {
|
||||||
|
return ((IHostFilePermissionsContainer) file).getPermissions();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFilePermissions(IHostFile file,
|
||||||
|
IHostFilePermissions permissions, IProgressMonitor monitor)
|
||||||
|
throws SystemMessageException {
|
||||||
|
Session session = getSession();
|
||||||
|
String path = ScpFileUtils.escapePath(file.getAbsolutePath());
|
||||||
|
int permBits = permissions.getPermissionBits();
|
||||||
|
String ownStr = permissions.getUserOwner() + ':'
|
||||||
|
+ permissions.getGroupOwner();
|
||||||
|
String cmd = "chmod " + Integer.toOctalString(permBits) + " " + path; //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
ScpFileUtils.execCommandSafe(session, cmd);
|
||||||
|
ScpFileUtils.execCommandSafe(session, "chown " + ownStr + " " + path); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
}
|
||||||
|
|
||||||
|
public void copy(String arg0, String arg1, String arg2, String arg3,
|
||||||
|
IProgressMonitor arg4) throws SystemMessageException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void copyBatch(String[] arg0, String[] arg1, String arg2,
|
||||||
|
IProgressMonitor arg3) throws SystemMessageException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public IHostFile createFile(String remotePath, String fileName,
|
||||||
|
IProgressMonitor arg2) throws SystemMessageException {
|
||||||
|
Session session = getSession();
|
||||||
|
String fullPath = ScpFileUtils.concat(remotePath, fileName);
|
||||||
|
|
||||||
|
ScpFileUtils.execCommandSafe(session,
|
||||||
|
"touch " + ScpFileUtils.escapePath(fullPath)); //$NON-NLS-1$
|
||||||
|
ScpFileAttr attr = ScpFileAttr.getAttr(session, fullPath);
|
||||||
|
|
||||||
|
return makeHostFile(remotePath, fileName, attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IHostFile createFolder(String remotePath, String fileName,
|
||||||
|
IProgressMonitor arg2) throws SystemMessageException {
|
||||||
|
Session session = getSession();
|
||||||
|
String fullPath = ScpFileUtils.concat(remotePath, fileName);
|
||||||
|
|
||||||
|
ScpFileUtils.execCommandSafe(session,
|
||||||
|
"mkdir " + ScpFileUtils.escapePath(fullPath)); //$NON-NLS-1$
|
||||||
|
ScpFileAttr attr = ScpFileAttr.getAttr(session, fullPath);
|
||||||
|
|
||||||
|
return makeHostFile(remotePath, fileName, attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void delete(String remotePath, String fileName, IProgressMonitor arg2)
|
||||||
|
throws SystemMessageException {
|
||||||
|
Session session = getSession();
|
||||||
|
String fullPathEsc = ScpFileUtils.concatEscape(remotePath, fileName);
|
||||||
|
|
||||||
|
ScpFileUtils.execCommandSafe(session, "rm -rf " + fullPathEsc); //$NON-NLS-1$
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String lastErrorMessage = null;
|
||||||
|
|
||||||
|
private static void setErrorMessage(String s) {
|
||||||
|
lastErrorMessage = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getLastError() {
|
||||||
|
return lastErrorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int readAck(InputStream is) throws IOException {
|
||||||
|
int rc = is.read();
|
||||||
|
if (rc <= 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* In case of non fatal error had to read an error string */
|
||||||
|
StringBuffer sb = new StringBuffer();
|
||||||
|
int ch;
|
||||||
|
do {
|
||||||
|
ch = is.read();
|
||||||
|
sb.append((char) ch);
|
||||||
|
} while (ch != ScpFileUtils.EOL_CHAR);
|
||||||
|
setErrorMessage(sb.toString());
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void download(String remoteParent, String fileName, File localFile,
|
||||||
|
boolean isBinary, String hostEncoding, IProgressMonitor monitor)
|
||||||
|
throws SystemMessageException {
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!localFile.exists()) {
|
||||||
|
File localParentFile = localFile.getParentFile();
|
||||||
|
if (!localParentFile.exists()) {
|
||||||
|
localParentFile.mkdirs();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internalDownload(remoteParent, fileName, localFile, monitor);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
throwSystemException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public IHostFile getFile(String remotePath, String fileName,
|
||||||
|
IProgressMonitor monitor) throws SystemMessageException {
|
||||||
|
Session session = getSession();
|
||||||
|
String fullPath = ScpFileUtils.concat(remotePath, fileName);
|
||||||
|
ScpFileAttr attr = ScpFileAttr.getAttr(session, fullPath);
|
||||||
|
|
||||||
|
return makeHostFile(remotePath, fileName, attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IHostFile[] getRoots(IProgressMonitor monitor)
|
||||||
|
throws SystemMessageException {
|
||||||
|
IHostFile root = null;
|
||||||
|
try {
|
||||||
|
root = getFile(null, ScpFileUtils.TARGET_SEPARATOR, monitor);
|
||||||
|
} catch (SystemMessageException e) {
|
||||||
|
Activator.warn("Failed to get root file", e);
|
||||||
|
}
|
||||||
|
if (root == null)
|
||||||
|
root = new SftpHostFile(null, ScpFileUtils.TARGET_SEPARATOR, true,
|
||||||
|
true, false, 0, 0);
|
||||||
|
|
||||||
|
return new IHostFile[] { root };
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public IHostFile getUserHome() {
|
||||||
|
if (fUserHome == null) {
|
||||||
|
try {
|
||||||
|
Session sess = getSession();
|
||||||
|
fUserHome = ScpFileUtils.execCommand(sess, "pwd").split( //$NON-NLS-1$
|
||||||
|
ScpFileUtils.EOL_STRING)[0];
|
||||||
|
} catch (Exception e) {
|
||||||
|
Activator.warn("Failed to execute pwd", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fUserHome == null)
|
||||||
|
return null;
|
||||||
|
int lastSlash = fUserHome
|
||||||
|
.lastIndexOf(ScpFileUtils.TARGET_SEPARATOR_CHAR);
|
||||||
|
String name = fUserHome.substring(lastSlash + 1);
|
||||||
|
String parent = fUserHome.substring(0, lastSlash);
|
||||||
|
IHostFile rc = null;
|
||||||
|
try {
|
||||||
|
rc = getFile(parent, name, null);
|
||||||
|
} catch (SystemMessageException e) {
|
||||||
|
Activator.warn("Failed to get user home file ", e);
|
||||||
|
}
|
||||||
|
if (rc == null)
|
||||||
|
rc = new SftpHostFile(null, fUserHome, true, true, false, 0, 0);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCaseSensitive() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void move(String oldPath, String oldName, String newPath,
|
||||||
|
String newName, IProgressMonitor arg4)
|
||||||
|
throws SystemMessageException {
|
||||||
|
Session session = getSession();
|
||||||
|
String oldFullPathEsc = ScpFileUtils.concatEscape(newPath, oldName);
|
||||||
|
String newFullPathEsc = ScpFileUtils.concatEscape(newPath, newName);
|
||||||
|
|
||||||
|
ScpFileUtils.execCommandSafe(session, "mv " + oldFullPathEsc + " " //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
+ newFullPathEsc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void rename(String remotePath, String oldName, String newName,
|
||||||
|
IProgressMonitor monitor) throws SystemMessageException {
|
||||||
|
Session session = getSession();
|
||||||
|
String oldFullPathEsc = ScpFileUtils.concatEscape(remotePath, oldName);
|
||||||
|
String newFullPathEsc = ScpFileUtils.concatEscape(remotePath, newName);
|
||||||
|
|
||||||
|
ScpFileUtils.execCommandSafe(session, "mv " + oldFullPathEsc + " " //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
+ newFullPathEsc);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void rename(String remotePath, String oldName, String newName,
|
||||||
|
IHostFile hostFile, IProgressMonitor monitor)
|
||||||
|
throws SystemMessageException {
|
||||||
|
// hostFile remains unused
|
||||||
|
rename(remotePath, oldName, newName, monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastModified(String arg0, String arg1, long arg2,
|
||||||
|
IProgressMonitor arg3) throws SystemMessageException {
|
||||||
|
throwSystemException("setLastModified() not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReadOnly(String remotePath, String fileName,
|
||||||
|
boolean disableWrite, IProgressMonitor monitor)
|
||||||
|
throws SystemMessageException {
|
||||||
|
Session session = getSession();
|
||||||
|
String fullPath = ScpFileUtils.concat(remotePath, fileName);
|
||||||
|
ScpFileAttr attr = ScpFileAttr.getAttr(session, fullPath);
|
||||||
|
if (attr == null)
|
||||||
|
throwSystemException("Can't get attribute of file " + fullPath);
|
||||||
|
int perm = new HostFilePermissions(attr.getAttrs(), "", "") //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
.getPermissionBits();
|
||||||
|
if (disableWrite)
|
||||||
|
perm &= ~0222;
|
||||||
|
else
|
||||||
|
perm |= 0200;
|
||||||
|
ScpFileUtils.execCommandSafe(
|
||||||
|
session,
|
||||||
|
"chmod " + Integer.toOctalString(perm) + " " //$NON-NLS-1$//$NON-NLS-2$
|
||||||
|
+ ScpFileUtils.escapePath(fullPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void upload(InputStream stream, String remotePath,
|
||||||
|
String remoteFile, boolean isBinary, String hostEncoding,
|
||||||
|
IProgressMonitor monitor) throws SystemMessageException {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void internalDownload(String remoteParent, String fileName,
|
||||||
|
File localFile, IProgressMonitor monitor) throws Exception {
|
||||||
|
String remotePath = ScpFileUtils.concat(remoteParent, fileName);
|
||||||
|
String cmd = "scp -f " + ScpFileUtils.escapePath(remotePath); //$NON-NLS-1$
|
||||||
|
|
||||||
|
ChannelExec ch = ScpFileUtils.openExecChannel(getSession(), cmd);
|
||||||
|
InputStream is = ch.getInputStream();
|
||||||
|
OutputStream os = ch.getOutputStream();
|
||||||
|
ch.connect();
|
||||||
|
|
||||||
|
byte buf[] = new byte[1024];
|
||||||
|
// send '0'
|
||||||
|
buf[0] = 0;
|
||||||
|
os.write(buf, 0, 1);
|
||||||
|
os.flush();
|
||||||
|
|
||||||
|
int c = is.read();
|
||||||
|
if (c == 1) {
|
||||||
|
String errmsg = ScpFileUtils.readString(is);
|
||||||
|
throw new Exception("Error while downloading " + remotePath + " :"
|
||||||
|
+ errmsg);
|
||||||
|
}
|
||||||
|
if (c != 'C')
|
||||||
|
throw new Exception("Error while downloading " + remotePath
|
||||||
|
+ ": Can't download file of type" + c);
|
||||||
|
|
||||||
|
// read '0644'
|
||||||
|
is.read(buf, 0, 5);
|
||||||
|
|
||||||
|
// get file size
|
||||||
|
long filesize = 0;
|
||||||
|
while (true) {
|
||||||
|
if (is.read(buf, 0, 1) < 0)
|
||||||
|
break;
|
||||||
|
if (buf[0] == ' ')
|
||||||
|
break;
|
||||||
|
filesize = filesize * 10 + (buf[0] - '0');
|
||||||
|
}
|
||||||
|
String fname = ScpFileUtils.readString(is);
|
||||||
|
|
||||||
|
Activator.log("filesize=" + filesize + " fname=" + fname);
|
||||||
|
|
||||||
|
// Confirm that file description is read by sending '0'
|
||||||
|
buf[0] = 0;
|
||||||
|
os.write(buf, 0, 1);
|
||||||
|
os.flush();
|
||||||
|
|
||||||
|
FileOutputStream fos = new FileOutputStream(localFile);
|
||||||
|
monitor.beginTask("Downloading file", (int) filesize);
|
||||||
|
long bytesDownloaded = 0;
|
||||||
|
while (true) {
|
||||||
|
int len = buf.length;
|
||||||
|
if (filesize - bytesDownloaded < len)
|
||||||
|
len = (int) (filesize - bytesDownloaded);
|
||||||
|
int rc = is.read(buf, 0, len);
|
||||||
|
if (rc < 0)
|
||||||
|
break;
|
||||||
|
monitor.worked(rc);
|
||||||
|
fos.write(buf, 0, rc);
|
||||||
|
bytesDownloaded += rc;
|
||||||
|
if (bytesDownloaded >= filesize)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fos.close();
|
||||||
|
fos = null;
|
||||||
|
monitor.done();
|
||||||
|
|
||||||
|
c = is.read();
|
||||||
|
if (c == 0) {
|
||||||
|
// Confirm that file was received by sending '0'
|
||||||
|
buf[0] = 0;
|
||||||
|
os.write(buf, 0, 1);
|
||||||
|
os.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
os.close();
|
||||||
|
is.close();
|
||||||
|
|
||||||
|
ch.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void internalUpload(File localFile, String remotePath,
|
||||||
|
String remoteFile, IProgressMonitor monitor) throws Exception {
|
||||||
|
|
||||||
|
monitor.beginTask("Uploading file", (int) localFile.length() + 10);
|
||||||
|
|
||||||
|
Session session = getSession();
|
||||||
|
String cmd = "scp -p -t " + ScpFileUtils.escapePath(remotePath); //$NON-NLS-1$
|
||||||
|
ChannelExec ch = ScpFileUtils.openExecChannel(session, cmd);
|
||||||
|
InputStream is = ch.getInputStream();
|
||||||
|
OutputStream os = ch.getOutputStream();
|
||||||
|
ch.connect();
|
||||||
|
monitor.internalWorked(5);
|
||||||
|
|
||||||
|
String fileHeader = "C0644" + " " + localFile.length() + " " //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$
|
||||||
|
+ remoteFile + "\n"; //$NON-NLS-1$
|
||||||
|
if (readAck(is) != 0)
|
||||||
|
throw new Exception("upload: wrong Ack! Last error:"
|
||||||
|
+ getLastError());
|
||||||
|
|
||||||
|
os.write(fileHeader.getBytes());
|
||||||
|
os.flush();
|
||||||
|
|
||||||
|
monitor.internalWorked(4);
|
||||||
|
|
||||||
|
FileInputStream fis = new FileInputStream(localFile);
|
||||||
|
|
||||||
|
byte[] buf = new byte[1024];
|
||||||
|
while (true) {
|
||||||
|
int len = fis.read(buf, 0, buf.length);
|
||||||
|
if (len <= 0)
|
||||||
|
break;
|
||||||
|
os.write(buf, 0, len);
|
||||||
|
monitor.internalWorked(len);
|
||||||
|
}
|
||||||
|
fis.close();
|
||||||
|
|
||||||
|
buf[0] = 0;
|
||||||
|
os.write(buf, 0, 1);
|
||||||
|
os.flush();
|
||||||
|
if (readAck(is) != 0)
|
||||||
|
throw new Exception("Error happened while uploading "
|
||||||
|
+ localFile.getAbsolutePath() + ":" + getLastError());
|
||||||
|
monitor.internalWorked(1);
|
||||||
|
|
||||||
|
os.close();
|
||||||
|
is.close();
|
||||||
|
monitor.done();
|
||||||
|
ch.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void upload(File localFile, String remotePath, String remoteFile,
|
||||||
|
boolean isBinary, String srcEncoding, String hostEncoding,
|
||||||
|
IProgressMonitor monitor) throws SystemMessageException {
|
||||||
|
|
||||||
|
try {
|
||||||
|
internalUpload(localFile, remotePath, remoteFile, monitor);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throwSystemException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private IHostFile makeHostFile(String remotePath, String fileName,
|
||||||
|
ScpFileAttr attr) {
|
||||||
|
boolean isRoot = (remotePath == null || remotePath.length() == 0);
|
||||||
|
if (attr == null)
|
||||||
|
return new SftpHostFile(isRoot ? null : remotePath, fileName,
|
||||||
|
false, isRoot, false, 0, 0);
|
||||||
|
|
||||||
|
boolean isLink = attr.isLink();
|
||||||
|
boolean isDir = attr.isDirectory();
|
||||||
|
if (fileName == null)
|
||||||
|
fileName = attr.getName();
|
||||||
|
SftpHostFile node = new SftpHostFile(isRoot ? null : remotePath,
|
||||||
|
fileName, isDir, isRoot, isLink, 1000L * attr.getMTime(),
|
||||||
|
attr.getSize());
|
||||||
|
if (isLink && attr.getLinkName() != null)
|
||||||
|
node.setLinkTarget(attr.getLinkName());
|
||||||
|
node.setPermissions(attr.getFilePermissions());
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "SSH/SCP File Service can be used to connect to embedded sshd implementations, which often lacks sftp service";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "SCP File Service";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,135 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2009, 2010 Mentor Graphics Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Nikita Shulga - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.rse.internal.subsystems.files.scp;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import org.eclipse.rse.services.clientserver.messages.SystemMessageException;
|
||||||
|
|
||||||
|
import com.jcraft.jsch.ChannelExec;
|
||||||
|
import com.jcraft.jsch.Session;
|
||||||
|
|
||||||
|
public class ScpFileUtils {
|
||||||
|
public static final String EOL_STRING = "\n"; //$NON-NLS-1$
|
||||||
|
public static final String TARGET_SEPARATOR = "/"; //$NON-NLS-1$
|
||||||
|
public static final String EXEC_CHANNEL = "exec"; //$NON-NLS-1$
|
||||||
|
public static final String QUOTATION_MARK = "\""; //$NON-NLS-1$
|
||||||
|
|
||||||
|
public static char EOL_CHAR = EOL_STRING.charAt(0);
|
||||||
|
public static char TARGET_SEPARATOR_CHAR = TARGET_SEPARATOR.charAt(0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concatenate a parent directory with a file name to form a new proper path
|
||||||
|
* name.
|
||||||
|
*
|
||||||
|
* This method was cloned from
|
||||||
|
* {@link org.eclipse.rse.internal.services.ssh.files.SftpFileService#concat}
|
||||||
|
*/
|
||||||
|
protected static String concat(String parentDir, String fileName) {
|
||||||
|
// See also {@link SftpHostFile#getAbsolutePath()}
|
||||||
|
if (parentDir == null || parentDir.length() == 0) {
|
||||||
|
// Looking at a Root
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuffer path = new StringBuffer(parentDir);
|
||||||
|
if (!parentDir.endsWith(TARGET_SEPARATOR))
|
||||||
|
path.append(TARGET_SEPARATOR_CHAR);
|
||||||
|
|
||||||
|
path.append(fileName);
|
||||||
|
return path.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ChannelExec openExecChannel(Session sess) throws Exception {
|
||||||
|
return (ChannelExec) sess.openChannel(EXEC_CHANNEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ChannelExec openExecChannel(Session sess, String cmd)
|
||||||
|
throws Exception {
|
||||||
|
ChannelExec ch = openExecChannel(sess);
|
||||||
|
if (ch != null)
|
||||||
|
ch.setCommand(cmd);
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String execCommand(Session sess, String command)
|
||||||
|
throws Exception {
|
||||||
|
ChannelExec ch = openExecChannel(sess, command);
|
||||||
|
ch.setInputStream(null);
|
||||||
|
ch.setErrStream(System.err, true);
|
||||||
|
InputStream is = ch.getInputStream();
|
||||||
|
ch.connect();
|
||||||
|
|
||||||
|
String str = readStream(ch);
|
||||||
|
is.close();
|
||||||
|
ch.disconnect();
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String execCommandSafe(Session session, String command)
|
||||||
|
throws SystemMessageException {
|
||||||
|
String rc = null;
|
||||||
|
try {
|
||||||
|
rc = execCommand(session, command);
|
||||||
|
} catch (Exception e) {
|
||||||
|
ScpFileService.throwSystemException(e);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String escapePath(String path) {
|
||||||
|
if (path.indexOf(' ') < 0)
|
||||||
|
return path;
|
||||||
|
return QUOTATION_MARK + path + QUOTATION_MARK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concatenates parent directory with file name and escape the result if
|
||||||
|
* necessary
|
||||||
|
*
|
||||||
|
* @param parentDir
|
||||||
|
* parent directory
|
||||||
|
* @param fileName
|
||||||
|
* file name
|
||||||
|
* @return escaped concatenated path to the file
|
||||||
|
*/
|
||||||
|
protected static String concatEscape(String parentDir, String fileName) {
|
||||||
|
return escapePath(concat(parentDir, fileName));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String readString(InputStream is) throws IOException {
|
||||||
|
StringBuffer buf = new StringBuffer();
|
||||||
|
int rc = 0;
|
||||||
|
while (true) {
|
||||||
|
rc = is.read();
|
||||||
|
if (rc == EOL_CHAR)
|
||||||
|
break;
|
||||||
|
buf.append((char) rc);
|
||||||
|
}
|
||||||
|
return buf.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String readStream(ChannelExec ch) throws IOException {
|
||||||
|
InputStream is = ch.getInputStream();
|
||||||
|
byte[] buf = new byte[1024];
|
||||||
|
String rc = ""; //$NON-NLS-1$
|
||||||
|
while (!ch.isClosed() || is.available() > 0) {
|
||||||
|
int cnt = is.read(buf, 0, buf.length);
|
||||||
|
if (cnt < 0)
|
||||||
|
break;
|
||||||
|
rc += new String(buf, 0, cnt);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2005, 2010 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Initial Contributors:
|
||||||
|
* The following IBM employees contributed to the Remote System Explorer
|
||||||
|
* component that contains this file: David McKnight, Kushal Munir,
|
||||||
|
* Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson,
|
||||||
|
* Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley.
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Martin Oberhuber (Wind River) - Adapted from FTPRemoteFile.
|
||||||
|
* Martin Oberhuber (Wind River) - [216343] immediate link targets and canonical paths for Sftp
|
||||||
|
* Nikita Shulga (Mentor Graphics) - Adapted from SftpRemoteFile.
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.rse.internal.subsystems.files.scp;
|
||||||
|
|
||||||
|
import org.eclipse.rse.internal.services.ssh.files.SftpHostFile;
|
||||||
|
import org.eclipse.rse.services.files.IHostFile;
|
||||||
|
import org.eclipse.rse.subsystems.files.core.servicesubsystem.AbstractRemoteFile;
|
||||||
|
import org.eclipse.rse.subsystems.files.core.servicesubsystem.FileServiceSubSystem;
|
||||||
|
import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFile;
|
||||||
|
import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFileContext;
|
||||||
|
|
||||||
|
@SuppressWarnings("restriction")
|
||||||
|
public class ScpRemoteFile extends AbstractRemoteFile {
|
||||||
|
|
||||||
|
public ScpRemoteFile(FileServiceSubSystem ss, IRemoteFileContext context,
|
||||||
|
IRemoteFile parent, IHostFile hostFile) {
|
||||||
|
super(ss, context, parent, hostFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SftpHostFile getSftpHostFile() {
|
||||||
|
return (SftpHostFile) getHostFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCanonicalPath() {
|
||||||
|
String canonicalPath = getSftpHostFile().getCanonicalPath();
|
||||||
|
if (canonicalPath.equals(getAbsolutePath()) && _parentFile != null) {
|
||||||
|
String parentCanonicalPath = _parentFile.getCanonicalPath();
|
||||||
|
StringBuffer path = new StringBuffer(parentCanonicalPath);
|
||||||
|
if (!parentCanonicalPath.endsWith(ScpFileUtils.TARGET_SEPARATOR))
|
||||||
|
path.append(ScpFileUtils.TARGET_SEPARATOR);
|
||||||
|
|
||||||
|
path.append(getName());
|
||||||
|
canonicalPath = path.toString();
|
||||||
|
}
|
||||||
|
return canonicalPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClassification() {
|
||||||
|
return getSftpHostFile().getClassification();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,103 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2006, 2010 Wind River Systems, Inc. and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Martin Oberhuber (Wind River) - initial API and implementation
|
||||||
|
* Nikita Shulga (Mentor Graphics) - adapted from SftpFileSubSystemConfiguration.
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.rse.subsystems.files.scp;
|
||||||
|
|
||||||
|
import org.eclipse.rse.core.model.IHost;
|
||||||
|
import org.eclipse.rse.core.subsystems.IConnectorService;
|
||||||
|
import org.eclipse.rse.core.subsystems.ISubSystem;
|
||||||
|
import org.eclipse.rse.internal.connectorservice.ssh.SshConnectorService;
|
||||||
|
import org.eclipse.rse.internal.connectorservice.ssh.SshConnectorServiceManager;
|
||||||
|
import org.eclipse.rse.internal.services.ssh.ISshService;
|
||||||
|
import org.eclipse.rse.internal.subsystems.files.scp.ScpFileAdapter;
|
||||||
|
import org.eclipse.rse.internal.subsystems.files.scp.ScpFileService;
|
||||||
|
|
||||||
|
import org.eclipse.rse.services.clientserver.SystemSearchString;
|
||||||
|
import org.eclipse.rse.services.files.IFileService;
|
||||||
|
import org.eclipse.rse.services.search.IHostSearchResultConfiguration;
|
||||||
|
import org.eclipse.rse.services.search.IHostSearchResultSet;
|
||||||
|
import org.eclipse.rse.services.search.ISearchService;
|
||||||
|
import org.eclipse.rse.subsystems.files.core.ILanguageUtilityFactory;
|
||||||
|
import org.eclipse.rse.subsystems.files.core.servicesubsystem.FileServiceSubSystem;
|
||||||
|
import org.eclipse.rse.subsystems.files.core.servicesubsystem.FileServiceSubSystemConfiguration;
|
||||||
|
import org.eclipse.rse.subsystems.files.core.subsystems.IHostFileToRemoteFileAdapter;
|
||||||
|
import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFileSubSystem;
|
||||||
|
|
||||||
|
@SuppressWarnings("restriction")
|
||||||
|
public class ScpFileSubSystemConfiguration extends
|
||||||
|
FileServiceSubSystemConfiguration {
|
||||||
|
|
||||||
|
protected IHostFileToRemoteFileAdapter _hostFileAdapter;
|
||||||
|
|
||||||
|
public ScpFileSubSystemConfiguration() {
|
||||||
|
super();
|
||||||
|
setIsUnixStyle(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ISubSystem createSubSystemInternal(IHost host) {
|
||||||
|
IConnectorService connectorService = getConnectorService(host);
|
||||||
|
IFileService fileService = getFileService(host);
|
||||||
|
ISubSystem subsys = new FileServiceSubSystem(host, connectorService,
|
||||||
|
fileService, getHostFileAdapter(), getSearchService(host));
|
||||||
|
return subsys;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IFileService createFileService(IHost host) {
|
||||||
|
SshConnectorService connectorService = (SshConnectorService) getConnectorService(host);
|
||||||
|
return new ScpFileService(connectorService);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IHostFileToRemoteFileAdapter getHostFileAdapter() {
|
||||||
|
if (_hostFileAdapter == null) {
|
||||||
|
_hostFileAdapter = new ScpFileAdapter();
|
||||||
|
}
|
||||||
|
return _hostFileAdapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ILanguageUtilityFactory getLanguageUtilityFactory(
|
||||||
|
IRemoteFileSubSystem arg0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IConnectorService getConnectorService(IHost host) {
|
||||||
|
return SshConnectorServiceManager.getInstance().getConnectorService(
|
||||||
|
host, getServiceImplType());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<?> getServiceImplType() {
|
||||||
|
return ISshService.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean supportsArchiveManagement() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean supportsFileTypes() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean supportsSearch() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ISearchService createSearchService(IHost arg0) {
|
||||||
|
// no search service supported for ssh/scp at moment
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IHostSearchResultConfiguration createSearchConfiguration(IHost arg0,
|
||||||
|
IHostSearchResultSet arg1, Object arg2, SystemSearchString arg3) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue