private bool CreateDirectory(SCPChannelStream stream, string directoryPath, SCPModTime modTime, Cancellation cancellation, SCPFileTransferProgressDelegate progressDelegate) { if (cancellation != null && cancellation.IsRequested) { return(false); // cancel } string directoryName = Path.GetFileName(directoryPath); if (progressDelegate != null) { progressDelegate(directoryPath, directoryName, SCPFileTransferStatus.CreateDirectory, 0, 0); } if (!Directory.Exists(directoryPath)) // skip if already exists { try { Directory.CreateDirectory(directoryPath); } catch (Exception e) { SendError(stream, "failed to create a directory"); throw new SCPClientException("Failed to create a directory: " + directoryPath, e); } } if (modTime != null) { try { Directory.SetLastWriteTimeUtc(directoryPath, modTime.MTime); Directory.SetLastAccessTimeUtc(directoryPath, modTime.ATime); } catch (Exception e) { SendError(stream, "failed to modify time of a directory"); throw new SCPClientException("Failed to modify time of a directory: " + directoryPath, e); } } stream.Write(ZERO); if (progressDelegate != null) { progressDelegate(directoryPath, directoryName, SCPFileTransferStatus.DirectoryCreated, 0, 0); } return(true); }
private bool CreateFile(SCPChannelStream stream, string filePath, SCPEntry entry, SCPModTime modTime, Cancellation cancellation, SCPFileTransferProgressDelegate progressDelegate) { string fileName = Path.GetFileName(filePath); ulong transmitted = 0; if (progressDelegate != null) { progressDelegate(filePath, fileName, SCPFileTransferStatus.Open, (ulong)entry.FileSize, transmitted); } FileStream fileStream; try { fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.Read); } catch (Exception e) { SendError(stream, "failed to create a file"); throw new SCPClientException("Failed to create a file: " + filePath, e); } stream.Write(ZERO); using (fileStream) { byte[] buff = new byte[FILE_TRANSFER_BLOCK_SIZE]; long remain = entry.FileSize; try { while (remain > 0) { if (cancellation != null && cancellation.IsRequested) { if (progressDelegate != null) { progressDelegate(filePath, fileName, SCPFileTransferStatus.CompletedAbort, (ulong)entry.FileSize, transmitted); } return(false); // cancel } int maxLength = (int)Math.Min((long)buff.Length, remain); int readLength = stream.Read(buff, maxLength, _protocolTimeout); fileStream.Write(buff, 0, readLength); remain -= readLength; transmitted += (ulong)readLength; if (progressDelegate != null) { progressDelegate(filePath, fileName, SCPFileTransferStatus.Transmitting, (ulong)entry.FileSize, transmitted); } } } catch (Exception e) { SendError(stream, "failed to write to a file"); throw new SCPClientException("Failed to write to a file: " + filePath, e); } } if (modTime != null) { try { File.SetLastWriteTimeUtc(filePath, modTime.MTime); File.SetLastAccessTimeUtc(filePath, modTime.ATime); } catch (Exception e) { SendError(stream, "failed to modify time of a file"); throw new SCPClientException("Failed to modify time of a file: " + filePath, e); } } CheckResponse(stream); stream.Write(ZERO); if (progressDelegate != null) { progressDelegate(filePath, fileName, SCPFileTransferStatus.CompletedSuccess, (ulong)entry.FileSize, transmitted); } return(true); }
private bool CreateFile(SCPChannelStream stream, string filePath, SCPEntry entry, SCPModTime modTime, Cancellation cancellation, SCPFileTransferProgressDelegate progressDelegate) { string fileName = Path.GetFileName(filePath); ulong transmitted = 0; if (progressDelegate != null) progressDelegate(filePath, fileName, SCPFileTransferStatus.Open, (ulong)entry.FileSize, transmitted); FileStream fileStream; try { fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.Read); } catch (Exception e) { SendError(stream, "failed to create a file"); throw new SCPClientException("Failed to create a file: " + filePath, e); } stream.Write(ZERO); using (fileStream) { byte[] buff = new byte[FILE_TRANSFER_BLOCK_SIZE]; long remain = entry.FileSize; try { while (remain > 0) { if (cancellation != null && cancellation.IsRequested) { if (progressDelegate != null) progressDelegate(filePath, fileName, SCPFileTransferStatus.CompletedAbort, (ulong)entry.FileSize, transmitted); return false; // cancel } int maxLength = (int)Math.Min((long)buff.Length, remain); int readLength = stream.Read(buff, maxLength, _protocolTimeout); fileStream.Write(buff, 0, readLength); remain -= readLength; transmitted += (ulong)readLength; if (progressDelegate != null) progressDelegate(filePath, fileName, SCPFileTransferStatus.Transmitting, (ulong)entry.FileSize, transmitted); } } catch (Exception e) { SendError(stream, "failed to write to a file"); throw new SCPClientException("Failed to write to a file: " + filePath, e); } } if (modTime != null) { try { File.SetLastWriteTimeUtc(filePath, modTime.MTime); File.SetLastAccessTimeUtc(filePath, modTime.ATime); } catch (Exception e) { SendError(stream, "failed to modify time of a file"); throw new SCPClientException("Failed to modify time of a file: " + filePath, e); } } CheckResponse(stream); stream.Write(ZERO); if (progressDelegate != null) progressDelegate(filePath, fileName, SCPFileTransferStatus.CompletedSuccess, (ulong)entry.FileSize, transmitted); return true; }
/// <summary> /// Download files or directories. /// </summary> /// <remarks> /// <para>Unfortunately, Granados sends a command line in the ASCII encoding. /// So the "remotePath" must be an ASCII text.</para> /// </remarks> /// <param name="remotePath">Remote path (Unix path)</param> /// <param name="localPath">Local path (Windows' path)</param> /// <param name="recursive">Specifies recursive mode</param> /// <param name="preserveTime">Specifies to preserve time of the directory or file.</param> /// <param name="cancellation">An object to request the cancellation. Set null if the cancellation is not needed.</param> /// <param name="progressDelegate">Delegate to notify progress. Set null if notification is not needed.</param> public void Download(string remotePath, string localPath, bool recursive, bool preserveTime, Cancellation cancellation, SCPFileTransferProgressDelegate progressDelegate) { if (!IsAscii(remotePath)) { throw new SCPClientException("Remote path must consist of ASCII characters."); } string absLocalPath = Path.GetFullPath(localPath); string command = "scp -f "; if (recursive) { command += "-r "; } if (preserveTime) { command += "-p "; } command += EscapeUnixPath(remotePath); string localBasePath = null; // local directory to store SCPModTime modTime = null; Stack <string> localBasePathStack = new Stack <string>(); using (SCPChannelStream stream = new SCPChannelStream()) { stream.Open(_connection, command, _protocolTimeout); stream.Write(ZERO); while (true) { byte[] lineBytes = stream.ReadUntil(LF, _protocolTimeout); if (lineBytes[0] == 1 || lineBytes[0] == 2) { // Warning or Error string message = _encoding.GetString(lineBytes, 1, lineBytes.Length - 2); throw new SCPClientException(message); } if (lineBytes[0] == 0x43 /*'C'*/ || lineBytes[0] == 0x44 /*'D'*/) { SCPEntry entry; try { entry = ParseEntry(lineBytes); } catch (Exception e) { SendError(stream, e.Message); throw; } if (entry.IsDirectory) { string directoryPath = DeterminePathToCreate(localBasePath, absLocalPath, entry); bool continued = CreateDirectory(stream, directoryPath, modTime, cancellation, progressDelegate); if (!continued) { break; } modTime = null; localBasePathStack.Push(localBasePath); localBasePath = directoryPath; } else { string filePath = DeterminePathToCreate(localBasePath, absLocalPath, entry); bool continued = CreateFile(stream, filePath, entry, modTime, cancellation, progressDelegate); if (!continued) { break; } modTime = null; if (!recursive) { break; } } } else if (lineBytes[0] == 0x54 /*'T'*/) { if (preserveTime) { try { modTime = ParseModTime(lineBytes); } catch (Exception e) { SendError(stream, e.Message); throw; } } stream.Write(ZERO); } else if (lineBytes[0] == 0x45 /*'E'*/) { if (localBasePathStack.Count > 0) { localBasePath = localBasePathStack.Pop(); if (localBasePath == null) { break; } } stream.Write(ZERO); } else { SendError(stream, "Invalid control"); throw new SCPClientException("Invalid control"); } } } }
private bool CreateDirectory(SCPChannelStream stream, string directoryPath, SCPModTime modTime, Cancellation cancellation, SCPFileTransferProgressDelegate progressDelegate) { if (cancellation != null && cancellation.IsRequested) { return false; // cancel } string directoryName = Path.GetFileName(directoryPath); if (progressDelegate != null) progressDelegate(directoryPath, directoryName, SCPFileTransferStatus.CreateDirectory, 0, 0); if (!Directory.Exists(directoryPath)) { // skip if already exists try { Directory.CreateDirectory(directoryPath); } catch (Exception e) { SendError(stream, "failed to create a directory"); throw new SCPClientException("Failed to create a directory: " + directoryPath, e); } } if (modTime != null) { try { Directory.SetLastWriteTimeUtc(directoryPath, modTime.MTime); Directory.SetLastAccessTimeUtc(directoryPath, modTime.ATime); } catch (Exception e) { SendError(stream, "failed to modify time of a directory"); throw new SCPClientException("Failed to modify time of a directory: " + directoryPath, e); } } stream.Write(ZERO); if (progressDelegate != null) progressDelegate(directoryPath, directoryName, SCPFileTransferStatus.DirectoryCreated, 0, 0); return true; }