Skip to content

Commit a48926b

Browse files
committed
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.
1 parent 2d3f116 commit a48926b

File tree

5 files changed

+103
-26
lines changed

5 files changed

+103
-26
lines changed

examples/echoserver/echoserver.c

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2030,6 +2030,42 @@ static int wsUserAuth(byte authType,
20302030
}
20312031

20322032

2033+
#ifdef WOLFSSH_SFTP
2034+
static int SetDefaultSftpPath(WOLFSSH* ssh, const char* defaultSftpPath)
2035+
{
2036+
char path[WOLFSSH_MAX_FILENAME];
2037+
char realPath[WOLFSSH_MAX_FILENAME];
2038+
int ret = 0;
2039+
2040+
if (defaultSftpPath == NULL) {
2041+
#ifdef USE_WINDOWS_API
2042+
if (GetCurrentDirectoryA(sizeof(path), path) == 0) {
2043+
ret = -1;
2044+
}
2045+
#else
2046+
if (getcwd(path, sizeof(path)) == NULL) {
2047+
ret = -1;
2048+
}
2049+
#endif
2050+
}
2051+
else {
2052+
WSTRNCPY(path, defaultSftpPath, sizeof(path));
2053+
path[sizeof(path) - 1] = 0;
2054+
}
2055+
2056+
if (ret == 0) {
2057+
path[sizeof(path) - 1] = 0;
2058+
wolfSSH_RealPath(NULL, path, realPath, sizeof(realPath));
2059+
if (wolfSSH_SFTP_SetDefaultPath(ssh, realPath) != WS_SUCCESS) {
2060+
ret = -1;
2061+
}
2062+
}
2063+
2064+
return ret;
2065+
}
2066+
#endif
2067+
2068+
20332069
static void ShowUsage(void)
20342070
{
20352071
printf("echoserver %s\n", LIBWOLFSSH_VERSION_STRING);
@@ -2451,12 +2487,9 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
24512487
}
24522488

24532489
#ifdef WOLFSSH_SFTP
2454-
if (defaultSftpPath) {
2455-
if (wolfSSH_SFTP_SetDefaultPath(ssh, defaultSftpPath)
2456-
!= WS_SUCCESS) {
2457-
fprintf(stderr, "Couldn't store default sftp path.\n");
2458-
WEXIT(EXIT_FAILURE);
2459-
}
2490+
if (SetDefaultSftpPath(ssh, defaultSftpPath) != 0) {
2491+
fprintf(stderr, "Couldn't store default sftp path.\n");
2492+
WEXIT(EXIT_FAILURE);
24602493
}
24612494
#endif
24622495

src/port.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,15 @@ int wfopen(WFILE** f, const char* filename, const char* mode)
166166

167167
#if defined(USE_WINDOWS_API) && (defined(WOLFSSH_SFTP) || defined(WOLFSSH_SCP))
168168

169+
static const char* TrimFileName(const char* f, size_t* fSz)
170+
{
171+
if (f != NULL && fSz != NULL && *fSz >= 3 && f[0] == '/' && f[2] == ':') {
172+
f++;
173+
*fSz--;
174+
}
175+
return f;
176+
}
177+
169178
void* WS_CreateFileA(const char* fileName, unsigned long desiredAccess,
170179
unsigned long shareMode, unsigned long creationDisposition,
171180
unsigned long flags, void* heap)
@@ -178,6 +187,8 @@ void* WS_CreateFileA(const char* fileName, unsigned long desiredAccess,
178187
errno_t error;
179188

180189
fileNameSz = WSTRLEN(fileName);
190+
fileName = TrimFileName(fileName, &fileNameSz);
191+
181192
error = mbstowcs_s(&unicodeFileNameSz, NULL, 0, fileName, 0);
182193
if (error)
183194
return INVALID_HANDLE_VALUE;
@@ -211,6 +222,8 @@ void* WS_FindFirstFileA(const char* fileName,
211222
errno_t error;
212223

213224
fileNameSz = WSTRLEN(fileName);
225+
fileName = TrimFileName(fileName, &fileNameSz);
226+
214227
error = mbstowcs_s(&unicodeFileNameSz, NULL, 0, fileName, 0);
215228
if (error)
216229
return INVALID_HANDLE_VALUE;
@@ -268,6 +281,8 @@ int WS_GetFileAttributesExA(const char* fileName, void* fileInfo, void* heap)
268281
errno_t error;
269282

270283
fileNameSz = WSTRLEN(fileName);
284+
fileName = TrimFileName(fileName, &fileNameSz);
285+
271286
error = mbstowcs_s(&unicodeFileNameSz, NULL, 0, fileName, 0);
272287
if (error != 0)
273288
return 0;
@@ -301,6 +316,8 @@ int WS_RemoveDirectoryA(const char* dirName, void* heap)
301316
errno_t error;
302317

303318
dirNameSz = WSTRLEN(dirName);
319+
dirName = TrimFileName(dirName, &dirNameSz);
320+
304321
error = mbstowcs_s(&unicodeDirNameSz, NULL, 0, dirName, 0);
305322
if (error != 0)
306323
return 0;
@@ -333,6 +350,8 @@ int WS_CreateDirectoryA(const char* dirName, void* heap)
333350
errno_t error;
334351

335352
dirNameSz = WSTRLEN(dirName);
353+
dirName = TrimFileName(dirName, &dirNameSz);
354+
336355
error = mbstowcs_s(&unicodeDirNameSz, NULL, 0, dirName, 0);
337356
if (error != 0)
338357
return 0;
@@ -368,6 +387,7 @@ int WS_MoveFileA(const char* oldName, const char* newName, void* heap)
368387
errno_t error;
369388

370389
oldNameSz = WSTRLEN(oldName);
390+
oldName = TrimFileName(oldName, &oldNameSz);
371391

372392
error = mbstowcs_s(&unicodeOldNameSz, NULL, 0, oldName, 0);
373393
if (error != 0)
@@ -382,6 +402,8 @@ int WS_MoveFileA(const char* oldName, const char* newName, void* heap)
382402
oldName, oldNameSz);
383403

384404
newNameSz = WSTRLEN(newName);
405+
newName = TrimFileName(newName, &newNameSz);
406+
385407
error = mbstowcs_s(&unicodeNewNameSz, NULL, 0, newName, 0);
386408
if (error != 0)
387409
return 0;
@@ -417,6 +439,8 @@ int WS_DeleteFileA(const char* fileName, void* heap)
417439
errno_t error;
418440

419441
fileNameSz = WSTRLEN(fileName);
442+
fileName = TrimFileName(fileName, &fileNameSz);
443+
420444
error = mbstowcs_s(&unicodeFileNameSz, NULL, 0, fileName, 0);
421445
if (error != 0)
422446
return 0;

src/ssh.c

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2274,6 +2274,11 @@ int wolfSSH_ChannelGetEof(WOLFSSH_CHANNEL* channel)
22742274

22752275
#if (defined(WOLFSSH_SFTP) || defined(WOLFSSH_SCP)) && \
22762276
!defined(NO_WOLFSSH_SERVER)
2277+
2278+
#define DELIM "/\\"
2279+
#define IS_DELIM(x) ((x) == '/' || (x) == '\\')
2280+
#define IS_WINPATH(x,y) ((x) > 1 && (y)[1] == ':')
2281+
22772282
/*
22782283
* Paths starting with a slash are absolute, rooted at "/". Any path that
22792284
* 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,
23112316

23122317
WMEMSET(out, 0, outSz);
23132318
inSz = (word32)WSTRLEN(in);
2314-
if ((inSz == 0 || in[0] != '/') && defaultPath != NULL){
2315-
WSTRNCPY(out, defaultPath, outSz);
2316-
}
2317-
else {
2318-
out[0] = '/';
2319+
out[0] = '/';
2320+
if (inSz == 0 || (!IS_DELIM(in[0]) && !IS_WINPATH(inSz, in))) {
2321+
if (defaultPath != NULL) {
2322+
WSTRNCPY(out, defaultPath, outSz);
2323+
}
23192324
}
23202325
out[outSz - 1] = 0;
23212326
curSz = (word32)WSTRLEN(out);
23222327

2323-
for (seg = WSTRTOK(in, "/", &tail); seg; seg = WSTRTOK(NULL, "/", &tail)) {
2328+
for (seg = WSTRTOK(in, DELIM, &tail);
2329+
seg;
2330+
seg = WSTRTOK(NULL, DELIM, &tail)) {
23242331
segSz = (word32)WSTRLEN(seg);
23252332

23262333
/* Try to match "." */

src/wolfsftp.c

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2265,8 +2265,10 @@ int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
22652265
int i;
22662266

22672267
WMEMSET(ssh->driveList, 0, sizeof ssh->driveList);
2268+
ssh->driveListCount = 0;
2269+
22682270
drives = GetLogicalDrives();
2269-
for (i = 0, mask = 1; i < 26; i++, mask <<= 1) {
2271+
for (i = 0, mask = 1; i < (sizeof ssh->driveList); i++, mask <<= 1) {
22702272
if (drives & mask) {
22712273
driveName[0] = 'A' + i;
22722274
driveType = GetDriveTypeA(driveName);
@@ -2649,7 +2651,7 @@ static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR* dir, WS_SFTPNAME* out,
26492651
static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR* dir, WS_SFTPNAME* out,
26502652
char* dirName)
26512653
{
2652-
int sz;
2654+
int sz, special = 0;
26532655
HANDLE findHandle;
26542656
char realFileName[MAX_PATH];
26552657

@@ -2658,13 +2660,13 @@ static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR* dir, WS_SFTPNAME* out,
26582660
}
26592661

26602662
/* special case of getting drives at "/" */
2661-
if (dirName[0] == "/" && dirName[1] == 0) {
2663+
if (dirName[0] == '/' && dirName[1] == 0) {
26622664
if (ssh->driveIdx >= ssh->driveListCount)
26632665
return WS_FATAL_ERROR;
26642666
realFileName[0] = ssh->driveList[ssh->driveIdx++];
26652667
realFileName[1] = ':';
2666-
realFileName[2] = '/';
2667-
realFileName[3] = '\0';
2668+
realFileName[2] = '\0';
2669+
special = 1;
26682670
}
26692671
else if (*dir == INVALID_HANDLE_VALUE) {
26702672
char name[MAX_PATH];
@@ -2714,16 +2716,21 @@ static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR* dir, WS_SFTPNAME* out,
27142716
return WS_MEMORY_E;
27152717
}
27162718
buf[0] = '\0';
2717-
WSTRNCAT(buf, dirName, bufSz + 1);
2718-
tmpSz = (int)WSTRLEN(buf);
2719-
2720-
/* add delimiter between path and file/dir name */
2721-
if (tmpSz + 1 < bufSz) {
2722-
buf[tmpSz] = WS_DELIM;
2723-
buf[tmpSz + 1] = '\0';
2719+
if (!special) {
2720+
WSTRNCAT(buf, dirName, bufSz + 1);
2721+
tmpSz = (int)WSTRLEN(buf);
2722+
2723+
/* add delimiter between path and file/dir name */
2724+
if (tmpSz + 1 < bufSz) {
2725+
buf[tmpSz] = WS_DELIM;
2726+
buf[tmpSz + 1] = '\0';
2727+
}
2728+
WSTRNCAT(buf, out->fName, bufSz + 1);
2729+
}
2730+
else {
2731+
WSTRNCAT(buf, realFileName, bufSz + 1);
2732+
WSTRNCAT(buf, "\\", bufSz + 1);
27242733
}
2725-
WSTRNCAT(buf, out->fName, bufSz + 1);
2726-
27272734
if (SFTP_GetAttributes(ssh->fs, buf, &out->atrb, 0, ssh->ctx->heap)
27282735
!= WS_SUCCESS) {
27292736
WLOG(WS_LOG_SFTP, "Unable to get attribute values for %s",

tests/api.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1050,6 +1050,12 @@ struct RealPathTestCase realPathDefault[] = {
10501050
{ "./sample.jpg", "/C:/Users/fred/sample.jpg" },
10511051
{ "./sample./other", "/C:/Users/fred/sample./other" },
10521052
{ "./sample.dir/other", "/C:/Users/fred/sample.dir/other" },
1053+
{ "\\C:\\Users\\fred\\Documents\\junk.txt",
1054+
"/C:/Users/fred/Documents/junk.txt" },
1055+
{ "C:\\Users\\fred\\Documents\\junk.txt",
1056+
"/C:/Users/fred/Documents/junk.txt" },
1057+
{ "/C:\\Users\\fred/Documents\\junk.txt",
1058+
"/C:/Users/fred/Documents/junk.txt" },
10531059
};
10541060

10551061
struct RealPathTestCase realPathNull[] = {

0 commit comments

Comments
 (0)