private async Task <StepResult> DoCopySingleFileAsync(CopyFileStep step) { byte[] sourceContents; /* Read source file */ if (step.Direction == FileCopyDirection.RemoteToLocal) { var command = new FetchResultRange { FilePath = new[] { step.SourcePath } }; var response = await _channel.SendWithReplyAsync <ResultRangeFetched>(command, _controller.CancellationToken); if (response.Status == FetchStatus.FileNotFound) { return(new StepResult(false, $"File is not found on the remote machine at {step.SourcePath}", "")); } sourceContents = response.Data; } else if (!ReadLocalFile(step.SourcePath, out sourceContents, out var error)) { return(new StepResult(false, error, "")); } /* Write target file */ if (step.Direction == FileCopyDirection.LocalToRemote) { ICommand command = new PutFileCommand { Data = sourceContents, Path = step.TargetPath }; if (step.UseCompression) { command = new CompressedCommand(command); } var response = await _channel.SendWithReplyAsync <PutFileResponse>(command, _controller.CancellationToken); if (response.Status == PutFileStatus.PermissionDenied) { return(new StepResult(false, $"Access to path {step.TargetPath} on the remote machine is denied", "")); } if (response.Status == PutFileStatus.OtherIOError) { return(new StepResult(false, $"File {step.TargetPath} could not be created on the remote machine", "")); } } else { try { Directory.CreateDirectory(Path.GetDirectoryName(step.TargetPath)); File.WriteAllBytes(step.TargetPath, sourceContents); } catch (UnauthorizedAccessException) { return(new StepResult(false, $"Access to path {step.TargetPath} on the local machine is denied", "")); } } return(new StepResult(true, "", "")); }
private async Task <StepResult> DoCopyDirectoryAsync(CopyFileStep step, IList <FileMetadata> sourceFiles, IList <FileMetadata> targetFiles) { // Retrieve source files var files = new List <PackedFile>(); bool SourceIdenticalToTarget(FileMetadata src) { foreach (var dst in targetFiles) { if (dst.RelativePath == src.RelativePath) { return(dst.Size == src.Size && dst.LastWriteTimeUtc == src.LastWriteTimeUtc); } } return(false); } var filesToGet = new List <string>(); foreach (var src in sourceFiles) { if (!src.IsDirectory && !(step.SkipIfNotModified && SourceIdenticalToTarget(src))) { filesToGet.Add(src.RelativePath); } } if (filesToGet.Count > 0) { if (step.Direction == FileCopyDirection.RemoteToLocal) { var command = new GetFilesCommand { RootPath = step.SourcePath, Paths = filesToGet.ToArray(), UseCompression = step.UseCompression }; var response = await _channel.SendWithReplyAsync <GetFilesResponse>(command, _controller.CancellationToken); if (response.Status != GetFilesStatus.Successful) { return(new StepResult(false, $"Unable to copy files from the remote machine", "The following files were requested:\r\n" + string.Join("; ", filesToGet) + "\r\n")); } files.AddRange(response.Files); } else { files.AddRange(PackedFile.PackFiles(step.SourcePath, filesToGet)); } } // Include empty directories foreach (var src in sourceFiles) { // ./ indicates the root directory if (src.IsDirectory && src.RelativePath != "./" && !(step.SkipIfNotModified && SourceIdenticalToTarget(src))) { files.Add(new PackedFile(Array.Empty <byte>(), src.RelativePath, src.LastWriteTimeUtc)); } } // Write source files and directories to the target directory if (files.Count == 0) { return(new StepResult(true, "", "No files were copied. Sizes and modification times are identical on the source and target sides.\r\n")); } if (step.Direction == FileCopyDirection.LocalToRemote) { ICommand command = new PutDirectoryCommand { Files = files.ToArray(), Path = step.TargetPath, PreserveTimestamps = step.PreserveTimestamps }; if (step.UseCompression) { command = new CompressedCommand(command); } var response = await _channel.SendWithReplyAsync <PutDirectoryResponse>(command, _controller.CancellationToken); if (response.Status == PutDirectoryStatus.TargetPathIsFile) { return(new StepResult(false, $"Directory \"{step.SourcePath}\" could not be copied to the remote machine: the target path is a file.", "")); } if (response.Status == PutDirectoryStatus.PermissionDenied) { return(new StepResult(false, $"Access to path \"{step.TargetPath}\" on the remote machine is denied", "")); } if (response.Status == PutDirectoryStatus.OtherIOError) { return(new StepResult(false, $"Directory \"{step.SourcePath}\" could not be copied to the remote machine", "")); } } else { if (File.Exists(step.TargetPath)) { return(new StepResult(false, $"Directory \"{step.TargetPath}\" could not be copied to the local machine: the target path is a file.", "")); } try { PackedFile.UnpackFiles(step.TargetPath, files, step.PreserveTimestamps); } catch (UnauthorizedAccessException) { return(new StepResult(false, $"Access to path \"{step.TargetPath}\" on the local machine is denied", "")); } catch (IOException) { return(new StepResult(false, $"Directory \"{step.TargetPath}\" could not be copied to the local machine", "")); } } return(new StepResult(true, "", "")); }