mirror of https://github.com/wolfSSL/wolfssh.git
SFTP List
1. Update wolfSSH_SFTPNAME_readdir() to have a special case getting the drive letters at root in Windows. 2. The Win32 APIs can use forward slashes, but cannot have one at the beginning of the path before the drive letter. Add a trim function to remove the leading slash in the SFTP paths. 3. Update echoserver to always set the default SFTP path to either the provided command line option or to the CWD for the echoserver run. 4. Get the RealPath for the default path 5. Tweak wolfSSH_RealPath() to handle some Windows cases. 6. Added more test cases.pull/436/head
parent
2d3f11634a
commit
a48926b0dd
|
@ -2030,6 +2030,42 @@ static int wsUserAuth(byte authType,
|
|||
}
|
||||
|
||||
|
||||
#ifdef WOLFSSH_SFTP
|
||||
static int SetDefaultSftpPath(WOLFSSH* ssh, const char* defaultSftpPath)
|
||||
{
|
||||
char path[WOLFSSH_MAX_FILENAME];
|
||||
char realPath[WOLFSSH_MAX_FILENAME];
|
||||
int ret = 0;
|
||||
|
||||
if (defaultSftpPath == NULL) {
|
||||
#ifdef USE_WINDOWS_API
|
||||
if (GetCurrentDirectoryA(sizeof(path), path) == 0) {
|
||||
ret = -1;
|
||||
}
|
||||
#else
|
||||
if (getcwd(path, sizeof(path)) == NULL) {
|
||||
ret = -1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
WSTRNCPY(path, defaultSftpPath, sizeof(path));
|
||||
path[sizeof(path) - 1] = 0;
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
path[sizeof(path) - 1] = 0;
|
||||
wolfSSH_RealPath(NULL, path, realPath, sizeof(realPath));
|
||||
if (wolfSSH_SFTP_SetDefaultPath(ssh, realPath) != WS_SUCCESS) {
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void ShowUsage(void)
|
||||
{
|
||||
printf("echoserver %s\n", LIBWOLFSSH_VERSION_STRING);
|
||||
|
@ -2451,12 +2487,9 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
|
|||
}
|
||||
|
||||
#ifdef WOLFSSH_SFTP
|
||||
if (defaultSftpPath) {
|
||||
if (wolfSSH_SFTP_SetDefaultPath(ssh, defaultSftpPath)
|
||||
!= WS_SUCCESS) {
|
||||
fprintf(stderr, "Couldn't store default sftp path.\n");
|
||||
WEXIT(EXIT_FAILURE);
|
||||
}
|
||||
if (SetDefaultSftpPath(ssh, defaultSftpPath) != 0) {
|
||||
fprintf(stderr, "Couldn't store default sftp path.\n");
|
||||
WEXIT(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
24
src/port.c
24
src/port.c
|
@ -166,6 +166,15 @@ int wfopen(WFILE** f, const char* filename, const char* mode)
|
|||
|
||||
#if defined(USE_WINDOWS_API) && (defined(WOLFSSH_SFTP) || defined(WOLFSSH_SCP))
|
||||
|
||||
static const char* TrimFileName(const char* f, size_t* fSz)
|
||||
{
|
||||
if (f != NULL && fSz != NULL && *fSz >= 3 && f[0] == '/' && f[2] == ':') {
|
||||
f++;
|
||||
*fSz--;
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
void* WS_CreateFileA(const char* fileName, unsigned long desiredAccess,
|
||||
unsigned long shareMode, unsigned long creationDisposition,
|
||||
unsigned long flags, void* heap)
|
||||
|
@ -178,6 +187,8 @@ void* WS_CreateFileA(const char* fileName, unsigned long desiredAccess,
|
|||
errno_t error;
|
||||
|
||||
fileNameSz = WSTRLEN(fileName);
|
||||
fileName = TrimFileName(fileName, &fileNameSz);
|
||||
|
||||
error = mbstowcs_s(&unicodeFileNameSz, NULL, 0, fileName, 0);
|
||||
if (error)
|
||||
return INVALID_HANDLE_VALUE;
|
||||
|
@ -211,6 +222,8 @@ void* WS_FindFirstFileA(const char* fileName,
|
|||
errno_t error;
|
||||
|
||||
fileNameSz = WSTRLEN(fileName);
|
||||
fileName = TrimFileName(fileName, &fileNameSz);
|
||||
|
||||
error = mbstowcs_s(&unicodeFileNameSz, NULL, 0, fileName, 0);
|
||||
if (error)
|
||||
return INVALID_HANDLE_VALUE;
|
||||
|
@ -268,6 +281,8 @@ int WS_GetFileAttributesExA(const char* fileName, void* fileInfo, void* heap)
|
|||
errno_t error;
|
||||
|
||||
fileNameSz = WSTRLEN(fileName);
|
||||
fileName = TrimFileName(fileName, &fileNameSz);
|
||||
|
||||
error = mbstowcs_s(&unicodeFileNameSz, NULL, 0, fileName, 0);
|
||||
if (error != 0)
|
||||
return 0;
|
||||
|
@ -301,6 +316,8 @@ int WS_RemoveDirectoryA(const char* dirName, void* heap)
|
|||
errno_t error;
|
||||
|
||||
dirNameSz = WSTRLEN(dirName);
|
||||
dirName = TrimFileName(dirName, &dirNameSz);
|
||||
|
||||
error = mbstowcs_s(&unicodeDirNameSz, NULL, 0, dirName, 0);
|
||||
if (error != 0)
|
||||
return 0;
|
||||
|
@ -333,6 +350,8 @@ int WS_CreateDirectoryA(const char* dirName, void* heap)
|
|||
errno_t error;
|
||||
|
||||
dirNameSz = WSTRLEN(dirName);
|
||||
dirName = TrimFileName(dirName, &dirNameSz);
|
||||
|
||||
error = mbstowcs_s(&unicodeDirNameSz, NULL, 0, dirName, 0);
|
||||
if (error != 0)
|
||||
return 0;
|
||||
|
@ -368,6 +387,7 @@ int WS_MoveFileA(const char* oldName, const char* newName, void* heap)
|
|||
errno_t error;
|
||||
|
||||
oldNameSz = WSTRLEN(oldName);
|
||||
oldName = TrimFileName(oldName, &oldNameSz);
|
||||
|
||||
error = mbstowcs_s(&unicodeOldNameSz, NULL, 0, oldName, 0);
|
||||
if (error != 0)
|
||||
|
@ -382,6 +402,8 @@ int WS_MoveFileA(const char* oldName, const char* newName, void* heap)
|
|||
oldName, oldNameSz);
|
||||
|
||||
newNameSz = WSTRLEN(newName);
|
||||
newName = TrimFileName(newName, &newNameSz);
|
||||
|
||||
error = mbstowcs_s(&unicodeNewNameSz, NULL, 0, newName, 0);
|
||||
if (error != 0)
|
||||
return 0;
|
||||
|
@ -417,6 +439,8 @@ int WS_DeleteFileA(const char* fileName, void* heap)
|
|||
errno_t error;
|
||||
|
||||
fileNameSz = WSTRLEN(fileName);
|
||||
fileName = TrimFileName(fileName, &fileNameSz);
|
||||
|
||||
error = mbstowcs_s(&unicodeFileNameSz, NULL, 0, fileName, 0);
|
||||
if (error != 0)
|
||||
return 0;
|
||||
|
|
19
src/ssh.c
19
src/ssh.c
|
@ -2274,6 +2274,11 @@ int wolfSSH_ChannelGetEof(WOLFSSH_CHANNEL* channel)
|
|||
|
||||
#if (defined(WOLFSSH_SFTP) || defined(WOLFSSH_SCP)) && \
|
||||
!defined(NO_WOLFSSH_SERVER)
|
||||
|
||||
#define DELIM "/\\"
|
||||
#define IS_DELIM(x) ((x) == '/' || (x) == '\\')
|
||||
#define IS_WINPATH(x,y) ((x) > 1 && (y)[1] == ':')
|
||||
|
||||
/*
|
||||
* Paths starting with a slash are absolute, rooted at "/". Any path that
|
||||
* doesn't have a starting slash is assumed to be relative to the default
|
||||
|
@ -2311,16 +2316,18 @@ int wolfSSH_RealPath(const char* defaultPath, char* in,
|
|||
|
||||
WMEMSET(out, 0, outSz);
|
||||
inSz = (word32)WSTRLEN(in);
|
||||
if ((inSz == 0 || in[0] != '/') && defaultPath != NULL){
|
||||
WSTRNCPY(out, defaultPath, outSz);
|
||||
}
|
||||
else {
|
||||
out[0] = '/';
|
||||
out[0] = '/';
|
||||
if (inSz == 0 || (!IS_DELIM(in[0]) && !IS_WINPATH(inSz, in))) {
|
||||
if (defaultPath != NULL) {
|
||||
WSTRNCPY(out, defaultPath, outSz);
|
||||
}
|
||||
}
|
||||
out[outSz - 1] = 0;
|
||||
curSz = (word32)WSTRLEN(out);
|
||||
|
||||
for (seg = WSTRTOK(in, "/", &tail); seg; seg = WSTRTOK(NULL, "/", &tail)) {
|
||||
for (seg = WSTRTOK(in, DELIM, &tail);
|
||||
seg;
|
||||
seg = WSTRTOK(NULL, DELIM, &tail)) {
|
||||
segSz = (word32)WSTRLEN(seg);
|
||||
|
||||
/* Try to match "." */
|
||||
|
|
|
@ -2265,8 +2265,10 @@ int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
|
|||
int i;
|
||||
|
||||
WMEMSET(ssh->driveList, 0, sizeof ssh->driveList);
|
||||
ssh->driveListCount = 0;
|
||||
|
||||
drives = GetLogicalDrives();
|
||||
for (i = 0, mask = 1; i < 26; i++, mask <<= 1) {
|
||||
for (i = 0, mask = 1; i < (sizeof ssh->driveList); i++, mask <<= 1) {
|
||||
if (drives & mask) {
|
||||
driveName[0] = 'A' + i;
|
||||
driveType = GetDriveTypeA(driveName);
|
||||
|
@ -2649,7 +2651,7 @@ static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR* dir, WS_SFTPNAME* out,
|
|||
static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR* dir, WS_SFTPNAME* out,
|
||||
char* dirName)
|
||||
{
|
||||
int sz;
|
||||
int sz, special = 0;
|
||||
HANDLE findHandle;
|
||||
char realFileName[MAX_PATH];
|
||||
|
||||
|
@ -2658,13 +2660,13 @@ static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR* dir, WS_SFTPNAME* out,
|
|||
}
|
||||
|
||||
/* special case of getting drives at "/" */
|
||||
if (dirName[0] == "/" && dirName[1] == 0) {
|
||||
if (dirName[0] == '/' && dirName[1] == 0) {
|
||||
if (ssh->driveIdx >= ssh->driveListCount)
|
||||
return WS_FATAL_ERROR;
|
||||
realFileName[0] = ssh->driveList[ssh->driveIdx++];
|
||||
realFileName[1] = ':';
|
||||
realFileName[2] = '/';
|
||||
realFileName[3] = '\0';
|
||||
realFileName[2] = '\0';
|
||||
special = 1;
|
||||
}
|
||||
else if (*dir == INVALID_HANDLE_VALUE) {
|
||||
char name[MAX_PATH];
|
||||
|
@ -2714,16 +2716,21 @@ static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR* dir, WS_SFTPNAME* out,
|
|||
return WS_MEMORY_E;
|
||||
}
|
||||
buf[0] = '\0';
|
||||
WSTRNCAT(buf, dirName, bufSz + 1);
|
||||
tmpSz = (int)WSTRLEN(buf);
|
||||
if (!special) {
|
||||
WSTRNCAT(buf, dirName, bufSz + 1);
|
||||
tmpSz = (int)WSTRLEN(buf);
|
||||
|
||||
/* add delimiter between path and file/dir name */
|
||||
if (tmpSz + 1 < bufSz) {
|
||||
buf[tmpSz] = WS_DELIM;
|
||||
buf[tmpSz + 1] = '\0';
|
||||
/* add delimiter between path and file/dir name */
|
||||
if (tmpSz + 1 < bufSz) {
|
||||
buf[tmpSz] = WS_DELIM;
|
||||
buf[tmpSz + 1] = '\0';
|
||||
}
|
||||
WSTRNCAT(buf, out->fName, bufSz + 1);
|
||||
}
|
||||
else {
|
||||
WSTRNCAT(buf, realFileName, bufSz + 1);
|
||||
WSTRNCAT(buf, "\\", bufSz + 1);
|
||||
}
|
||||
WSTRNCAT(buf, out->fName, bufSz + 1);
|
||||
|
||||
if (SFTP_GetAttributes(ssh->fs, buf, &out->atrb, 0, ssh->ctx->heap)
|
||||
!= WS_SUCCESS) {
|
||||
WLOG(WS_LOG_SFTP, "Unable to get attribute values for %s",
|
||||
|
|
|
@ -1050,6 +1050,12 @@ struct RealPathTestCase realPathDefault[] = {
|
|||
{ "./sample.jpg", "/C:/Users/fred/sample.jpg" },
|
||||
{ "./sample./other", "/C:/Users/fred/sample./other" },
|
||||
{ "./sample.dir/other", "/C:/Users/fred/sample.dir/other" },
|
||||
{ "\\C:\\Users\\fred\\Documents\\junk.txt",
|
||||
"/C:/Users/fred/Documents/junk.txt" },
|
||||
{ "C:\\Users\\fred\\Documents\\junk.txt",
|
||||
"/C:/Users/fred/Documents/junk.txt" },
|
||||
{ "/C:\\Users\\fred/Documents\\junk.txt",
|
||||
"/C:/Users/fred/Documents/junk.txt" },
|
||||
};
|
||||
|
||||
struct RealPathTestCase realPathNull[] = {
|
||||
|
|
Loading…
Reference in New Issue