SCP Fixes (from Yanbing), realpath_win cleanup and spawn_child fix (that broke progfiles installation)

This commit is contained in:
Manoj Ampalam 2016-12-21 21:17:14 -08:00 committed by GitHub
parent c957488af2
commit 9333a08637
8 changed files with 94 additions and 141 deletions

View File

@ -155,11 +155,11 @@
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\win32_dirent.c" />
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\no-ops.c" />
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\win32_zlib.c" />
<ClCompile Include="..\win32compat\ansiprsr.c" />
<ClCompile Include="..\win32compat\conio.c" />
<ClCompile Include="..\win32compat\console.c" />
<ClCompile Include="..\win32compat\tncon.c" />
<ClCompile Include="..\win32compat\tnnet.c" />
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\ansiprsr.c" />
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\conio.c" />
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\console.c" />
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\tncon.c" />
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\tnnet.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\w32fd.h" />
@ -198,6 +198,7 @@
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\inc\termios.h" />
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\inc\dirent.h" />
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\inc\pwd.h" />
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\misc_internal.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View File

@ -117,6 +117,7 @@
<Filter>inc</Filter>
</ClInclude>
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\inc\pwd.h" />
<ClInclude Include="..\win32compat\misc_internal.h" />
</ItemGroup>
<ItemGroup>
<Filter Include="inc">

View File

@ -36,6 +36,7 @@
#include "inc\sys\time.h"
#include <time.h>
#include <Shlwapi.h>
#include "misc_internal.h"
int usleep(unsigned int useconds)
{
@ -302,11 +303,25 @@ spawn_child(char* cmd, int in, int out, int err, DWORD flags) {
PROCESS_INFORMATION pi;
STARTUPINFOW si;
BOOL b;
char* abs_cmd;
char *abs_cmd, *t;
wchar_t * cmd_utf16;
int add_module_path = 0;
/* relative ? if so, add current module path to start */
if (!(cmd && cmd[0] != '\0' && (cmd[1] == ':' || cmd[0] == '\\' || cmd[0] == '.'))) {
/* should module path be added */
do{
if(!cmd)
break;
t = cmd;
if (*t = '\"')
t++;
if (t[0] == '\0' || t[0] == '\\' || t[0] == '.' || t[1] == ':')
break;
add_module_path = 1;
} while (0);
/* add current module path to start if needed */
if (add_module_path) {
char* ctr;
abs_cmd = malloc(strlen(w32_programdir()) + 1 + strlen(cmd) + 1);
if (abs_cmd == NULL) {
@ -478,8 +493,6 @@ w32_chown(const char *pathname, unsigned int owner, unsigned int group) {
return -1;
}
char *realpath_win(const char *path, char resolved[MAX_PATH]);
int
w32_utimes(const char *filename, struct timeval *tvp) {
struct utimbuf ub;
@ -487,10 +500,7 @@ w32_utimes(const char *filename, struct timeval *tvp) {
ub.modtime = tvp[1].tv_sec;
int ret;
// Skip the first '/' in the pathname
char resolvedPathName[MAX_PATH];
realpath_win(filename, resolvedPathName);
wchar_t *resolvedPathName_utf16 = utf8_to_utf16(resolvedPathName);
wchar_t *resolvedPathName_utf16 = utf8_to_utf16(sanitized_path(filename));
if (resolvedPathName_utf16 == NULL) {
errno = ENOMEM;
return -1;
@ -517,16 +527,9 @@ link(const char *oldpath, const char *newpath) {
int
w32_rename(const char *old_name, const char *new_name) {
// Skip the first '/' in the pathname
char resolvedOldPathName[MAX_PATH];
realpath_win(old_name, resolvedOldPathName);
wchar_t *resolvedOldPathName_utf16 = utf8_to_utf16(sanitized_path(old_name));
wchar_t *resolvedNewPathName_utf16 = utf8_to_utf16(sanitized_path(new_name));
// Skip the first '/' in the pathname
char resolvedNewPathName[MAX_PATH];
realpath_win(new_name, resolvedNewPathName);
wchar_t *resolvedOldPathName_utf16 = utf8_to_utf16(resolvedOldPathName);
wchar_t *resolvedNewPathName_utf16 = utf8_to_utf16(resolvedNewPathName);
if (NULL == resolvedOldPathName_utf16 || NULL == resolvedNewPathName_utf16) {
errno = ENOMEM;
return -1;
@ -541,11 +544,8 @@ w32_rename(const char *old_name, const char *new_name) {
int
w32_unlink(const char *path) {
// Skip the first '/' in the pathname
char resolvedPathName[MAX_PATH];
realpath_win(path, resolvedPathName);
wchar_t *resolvedPathName_utf16 = utf8_to_utf16(resolvedPathName);
wchar_t *resolvedPathName_utf16 = utf8_to_utf16(sanitized_path(path));
if (NULL == resolvedPathName_utf16) {
errno = ENOMEM;
return -1;
@ -559,11 +559,7 @@ w32_unlink(const char *path) {
int
w32_rmdir(const char *path) {
// Skip the first '/' in the pathname
char resolvedPathName[MAX_PATH];
realpath_win(path, resolvedPathName);
wchar_t *resolvedPathName_utf16 = utf8_to_utf16(resolvedPathName);
wchar_t *resolvedPathName_utf16 = utf8_to_utf16(sanitized_path(path));
if (NULL == resolvedPathName_utf16) {
errno = ENOMEM;
return -1;
@ -606,11 +602,8 @@ w32_getcwd(char *buffer, int maxlen) {
int
w32_mkdir(const char *path_utf8, unsigned short mode) {
// Skip the first '/' in the pathname
char resolvedPathName[MAX_PATH];
realpath_win(path_utf8, resolvedPathName);
wchar_t *path_utf16 = utf8_to_utf16(resolvedPathName);
wchar_t *path_utf16 = utf8_to_utf16(sanitized_path(path_utf8));
if (path_utf16 == NULL) {
errno = ENOMEM;
return -1;
@ -632,22 +625,14 @@ getrnd(u_char *s, size_t len) {
int
w32_stat(const char *path, struct w32_stat *buf) {
// Skip the first '/' in the pathname
char resolvedPathName[MAX_PATH];
realpath_win(path, resolvedPathName);
return fileio_stat(resolvedPathName, (struct _stat64*)buf);
return fileio_stat(sanitized_path(path), (struct _stat64*)buf);
}
// if file is symbolic link, copy its link into "link" .
int
readlink(const char *path, char *link, int linklen)
{
// Skip the first '/' in the pathname
char resolvedPathName[MAX_PATH];
realpath_win(path, resolvedPathName);
strcpy_s(link, linklen, resolvedPathName);
strcpy_s(link, linklen, sanitized_path(path));
return 0;
}
@ -694,16 +679,6 @@ realpath(const char *path, char resolved[MAX_PATH]) {
return resolved;
}
// like realpathWin32() but takes out the first slash so that windows systems can work on the actual file or directory
char *
realpath_win(const char *path, char resolved[MAX_PATH]) {
char tempPath[MAX_PATH];
realpath(path, tempPath);
strncpy(resolved, &tempPath[1], sizeof(tempPath) - 1);
return resolved;
}
// Maximum reparse buffer info size. The max user defined reparse
// data is 16KB, plus there's a header.
#define MAX_REPARSE_SIZE 17000

View File

@ -0,0 +1,3 @@
/* removes first '/' for Windows paths that are unix styled. Ex: /c:/ab.cd */
#define sanitized_path(p) (((p)[0] == '/' && (p)[1] != '\0' && (p)[2] == ':')? (p)+1 : (p))

View File

@ -40,6 +40,7 @@
#include <winioctl.h>
#include "Shlwapi.h"
#include <sys\utime.h>
#include "misc_internal.h"
/* internal table that stores the fd to w32_io mapping*/
struct w32fd_table {
@ -347,7 +348,7 @@ w32_pipe(int *pfds) {
pio[0]->handle, pio[0], read_index, pio[1]->handle, pio[1], write_index);
return 0;
}
char *realpath_win(const char *path, char resolved[MAX_PATH]);
int
w32_open(const char *pathname, int flags, ...) {
int min_index = fd_table_get_min_index();
@ -357,18 +358,14 @@ w32_open(const char *pathname, int flags, ...) {
if (min_index == -1)
return -1;
// Skip the first '/' in the pathname
char resolvedPathName[MAX_PATH];
realpath_win(pathname, resolvedPathName);
pio = fileio_open(resolvedPathName, flags, 0);
pio = fileio_open(sanitized_path(pathname), flags, 0);
if (pio == NULL)
return -1;
pio->type = NONSOCK_FD;
fd_table_set(pio, min_index);
debug("open - handle:%p, io:%p, fd:%d", pio->handle, pio, min_index);
debug3("open - path:%s", resolvedPathName);
debug3("open - path:%s", pathname);
return min_index;
}

View File

@ -11,6 +11,7 @@
#include "inc\dirent.h"
#include "inc\libgen.h"
#include "misc_internal.h"
struct DIR_ {
@ -19,8 +20,6 @@ struct DIR_ {
int first;
};
char * realpath_win(const char *path, char resolved[MAX_PATH]);
/* Open a directory stream on NAME.
Return a DIR stream on the directory, or NULL if it could not be opened. */
DIR * opendir(const char *name)
@ -32,11 +31,7 @@ DIR * opendir(const char *name)
wchar_t* wname = NULL;
int needed;
// Skip the first '/' in the pathname
char resolvedPathName[MAX_PATH];
realpath_win(name, resolvedPathName);
if ((wname = utf8_to_utf16(resolvedPathName)) == NULL) {
if ((wname = utf8_to_utf16(sanitized_path(name))) == NULL) {
errno = ENOMEM;
return NULL;
}

View File

@ -27,12 +27,11 @@ Describe "Tests for scp command" -Tags "CI" {
$server.SetupServer($client)
$testData = @(
<# known issue 340
@{
Title = 'Simple copy local file to local file'
Source = $SourceFilePath
Destination = $DestinationFilePath
},#>
},
@{
Title = 'Simple copy local file to remote file'
Source = $SourceFilePath
@ -43,12 +42,11 @@ Describe "Tests for scp command" -Tags "CI" {
Source = "$($server.localAdminUserName)@$($server.MachineName):$SourceFilePath"
Destination = $DestinationFilePath
},
<# known issue 340
@{
Title = 'Simple copy local file to local dir'
Source = $SourceFilePath
Destination = $DestinationDir
},#>
},
@{
Title = 'simple copy local file to remote dir'
Source = $SourceFilePath
@ -121,7 +119,7 @@ Describe "Tests for scp command" -Tags "CI" {
$equal | Should Be $true
}
<#It 'Directory recursive Copy with -i option: <Title> ' -TestCases:$testData1 {
It 'Directory recursive Copy with -i option: <Title> ' -TestCases:$testData1 {
param([string]$Title, $Source, $Destination)
.\scp -r -i $identifyFile $Source $Destination
@ -129,10 +127,10 @@ Describe "Tests for scp command" -Tags "CI" {
$equal = @(Compare-Object (Get-Item -path $SourceDir ) (Get-Item -path (join-path $DestinationDir $SourceDirName) ) -Property Name, Length).Length -eq 0
$equal | Should Be $true
#known issue 364
#$equal = @(Compare-Object (Get-ChildItem -Recurse -path $SourceDir) (Get-ChildItem -Recurse -path (join-path $DestinationDir $SourceDirName) ) -Property Name, Length).Length -eq 0
#$equal | Should Be $true
}#>
$equal = @(Compare-Object (Get-ChildItem -Recurse -path $SourceDir) (Get-ChildItem -Recurse -path (join-path $DestinationDir $SourceDirName) ) -Property Name, Length).Length -eq 0
$equal | Should Be $true
}
}
#this context only run on windows
@ -154,32 +152,29 @@ Describe "Tests for scp command" -Tags "CI" {
It 'File Copy with -S option (positive)' {
.\scp -S .\ssh.exe $SourceFilePath "$($server.localAdminUserName)@$($server.MachineName):$DestinationFilePath"
#validate file content. DestPath is the path to the file.
$equal = @(Compare-Object (Get-ChildItem -path $SourceFilePath) (Get-ChildItem -path $DestinationFilePath) -Property Name, Length).Length -eq 0 #todo: add LastWriteTime in comparison when issue is fixed
$equal = @(Compare-Object (Get-ChildItem -path $SourceFilePath) (Get-ChildItem -path $DestinationFilePath) -Property Name, Length).Length -eq 0
$equal | Should Be $true
}
<#It 'File Copy with -p -c -v option: <Title> ' -TestCases:$testData {
param([string]$Title, $Source, $Destination)
.\scp -p -c aes128-ctr -C $Source $Destination #Todo: add -v after it is supported.
.\scp -p -c aes128-ctr -v -C $Source $Destination
#validate file content. DestPath is the path to the file.
$equal = @(Compare-Object (Get-ChildItem -path $SourceFilePath) (Get-ChildItem -path $DestinationFilePath) -Property Name, Length).Length -eq 0 #todo: add LastWriteTime in comparison when issue is fixed
$equal = @(Compare-Object (Get-ChildItem -path $SourceFilePath) (Get-ChildItem -path $DestinationFilePath) -Property Name, Length, LastWriteTime.DateTime).Length -eq 0
$equal | Should Be $true
}#>
<# known issue 369
It 'Directory recursive Copy with -v option: <Title> ' -TestCases:$testData1 {
It 'Directory recursive Copy with -r -p -v option: <Title> ' -TestCases:$testData1 {
param([string]$Title, $Source, $Destination)
.\scp -r -p -v $Source $Destination
.\scp -r -p $Source $Destination
$equal = @(Compare-Object (Get-Item -path $SourceDir ) (Get-Item -path (join-path $DestinationDir $SourceDirName) ) -Property Name, Length, LastWriteTime).Length -eq 0
$equal = @(Compare-Object (Get-Item -path $SourceDir ) (Get-Item -path (join-path $DestinationDir $SourceDirName) ) -Property Name, Length).Length -eq 0
$equal | Should Be $true
#known issue 364
#$equal = @(Compare-Object (Get-ChildItem -Recurse -path $SourceDir) (Get-ChildItem -Recurse -path (join-path $DestinationDir $SourceDirName) ) -Property Name, Length, LastWriteTime).Length -eq 0
#$equal | Should Be $true
}#>
$equal = @(Compare-Object (Get-ChildItem -Recurse -path $SourceDir) (Get-ChildItem -Recurse -path (join-path $DestinationDir $SourceDirName) ) -Property Name, Length, LastWriteTime.DateTime).Length -eq 0
$equal | Should Be $true
}
}
Context "Key based authentication with -i -C -q options. host keys are not secured on server" {
@ -192,23 +187,20 @@ Describe "Tests for scp command" -Tags "CI" {
.\scp -i $identifyFile -C -q $Source $Destination
#validate file content. DestPath is the path to the file.
$equal = @(Compare-Object (Get-ChildItem -path $SourceFilePath) (Get-ChildItem -path $DestinationFilePath) -Property Name, Length).Length -eq 0 # need to validate LastWriteTime after issue 356 is fixed.
$equal = @(Compare-Object (Get-ChildItem -path $SourceFilePath) (Get-ChildItem -path $DestinationFilePath) -Property Name, Length).Length -eq 0
$equal | Should Be $true
}
<#It 'Directory recursive Copy with -i and -q options: <Title> ' -TestCases:$testData1 {
It 'Directory recursive Copy with -i and -q options: <Title> ' -TestCases:$testData1 {
param([string]$Title, $Source, $Destination)
.\scp -i $identifyFile -r -q $Source $Destination
$equal = @(Compare-Object (Get-Item -path $SourceDir ) (Get-Item -path (join-path $DestinationDir $SourceDirName) ) -Property Name, Length).Length -eq 0
$equal | Should Be $true
#known issue 364
#$equal = @(Compare-Object (Get-ChildItem -Recurse -path $SourceDir) (Get-ChildItem -Recurse -path (join-path $DestinationDir $SourceDirName) ) -Property Name, Length).Length -eq 0
#$equal | Should Be $true
}#>
$equal = @(Compare-Object (Get-ChildItem -Recurse -path $SourceDir) (Get-ChildItem -Recurse -path (join-path $DestinationDir $SourceDirName) ) -Property Name, Length).Length -eq 0
$equal | Should Be $true
}
}
}

35
scp.c
View File

@ -598,15 +598,9 @@ main(int argc, char **argv)
* convert '\\' to '/' in rest of arguments
*/
{
char *s1, *s2;
int i;
for (i = 0; i < argc; i++) {
s1 = argv[i];
while ((s2 = strchr(s1, '\\')) != NULL) {
*s2 = '/';
s1 = s2 + 1;
}
}
for (i = 0; i < argc; i++)
convertToForwardslash(argv[i]);
}
#endif /* WINDOWS */
@ -831,8 +825,12 @@ tolocal(int argc, char **argv)
/* local to local on windows - need to use local native copy command */
struct stat stb;
int exists;
char *last;
exists = stat(argv[i], &stb) == 0;
/* convert '/' to '\\' */
convertToBackslash(argv[i]);
convertToBackslash(argv[i - 1]);
if (exists && (S_ISDIR(stb.st_mode))) {
addargs(&alist, "%s", _PATH_XCOPY);
if (iamrecursive)
@ -842,23 +840,13 @@ tolocal(int argc, char **argv)
addargs(&alist, "/Y /F /I");
addargs(&alist, "%s", argv[i]);
char *lastf = NULL, *lastr = NULL, *name;
if ((lastf = strrchr(argv[i], '/')) == NULL && (lastr = strrchr(argv[i], '\\')) == NULL)
name = argv[i];
else {
if (lastf)
name = lastf;
if (lastr)
name = lastr;
++name;
}
char * dest = argv[argc - 1];
int len = strlen(dest);
char * lastletter = dest + len - 1;
if ((last = strrchr(argv[i], '\\')) == NULL)
last = argv[i];
else
++last;
addargs(&alist, "%s%s%s", argv[argc - 1],
(lastletter == "\\" || lastletter == "/") ? "" : "\\", name);
strcmp(argv[argc - 1], "\\") ? "\\" : "", last);
} else {
addargs(&alist, "%s", _PATH_COPY);
addargs(&alist, "/Y");
@ -1541,3 +1529,4 @@ lostconn(int signo)
else
exit(1);
}