/* * Copyright (C)2009 - SSHJ Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.schmizz.sshj.xfer.scp; import net.schmizz.sshj.common.IOUtils; import net.schmizz.sshj.common.StreamCopier; import net.schmizz.sshj.xfer.LocalFileFilter; import net.schmizz.sshj.xfer.LocalSourceFile; import net.schmizz.sshj.xfer.TransferListener; import java.io.IOException; import java.io.InputStream; /** Support for uploading files over a connected link using SCP. */ public class SCPUploadClient extends AbstractSCPClient { private LocalFileFilter uploadFilter; SCPUploadClient(SCPEngine engine) { super(engine); } SCPUploadClient(SCPEngine engine, int bandwidthLimit) { super(engine, bandwidthLimit); } /** Upload a local file from {@code localFile} to {@code targetPath} on the remote host. */ public synchronized int copy(LocalSourceFile sourceFile, String remotePath) throws IOException { return copy(sourceFile, remotePath, ScpCommandLine.EscapeMode.SingleQuote); } public synchronized int copy(LocalSourceFile sourceFile, String remotePath, ScpCommandLine.EscapeMode escapeMode) throws IOException { engine.cleanSlate(); try { startCopy(sourceFile, remotePath, escapeMode); } finally { engine.exit(); } return engine.getExitStatus(); } public void setUploadFilter(LocalFileFilter uploadFilter) { this.uploadFilter = uploadFilter; } private void startCopy(LocalSourceFile sourceFile, String targetPath, ScpCommandLine.EscapeMode escapeMode) throws IOException { ScpCommandLine commandLine = ScpCommandLine.with(ScpCommandLine.Arg.SINK) .and(ScpCommandLine.Arg.RECURSIVE) .and(ScpCommandLine.Arg.PRESERVE_TIMES, sourceFile.providesAtimeMtime()) .and(ScpCommandLine.Arg.LIMIT, String.valueOf(bandwidthLimit), (bandwidthLimit > 0)); commandLine.withPath(targetPath, escapeMode); engine.execSCPWith(commandLine); engine.check("Start status OK"); process(engine.getTransferListener(), sourceFile); } private void process(TransferListener listener, LocalSourceFile f) throws IOException { if (f.isDirectory()) { sendDirectory(listener.directory(f.getName()), f); } else if (f.isFile()) { sendFile(listener.file(f.getName(), f.getLength()), f); } else throw new IOException(f + " is not a regular file or directory"); } private void sendDirectory(TransferListener listener, LocalSourceFile f) throws IOException { preserveTimeIfPossible(f); engine.sendMessage("D0" + getPermString(f) + " 0 " + f.getName()); for (LocalSourceFile child : f.getChildren(uploadFilter)) process(listener, child); engine.sendMessage("E"); } private void sendFile(StreamCopier.Listener listener, LocalSourceFile f) throws IOException { preserveTimeIfPossible(f); final InputStream src = f.getInputStream(); try { engine.sendMessage("C0" + getPermString(f) + " " + f.getLength() + " " + f.getName()); engine.transferToRemote(listener, src, f.getLength()); engine.signal("Transfer done"); engine.check("Remote agrees transfer done"); } finally { IOUtils.closeQuietly(src); } } private void preserveTimeIfPossible(LocalSourceFile f) throws IOException { if (f.providesAtimeMtime()) engine.sendMessage("T" + f.getLastModifiedTime() + " 0 " + f.getLastAccessTime() + " 0"); } private String getPermString(LocalSourceFile f) throws IOException { return Integer.toOctalString(f.getPermissions() & 07777); } }