port, scp: distinguish end of directory from enumeration failure

- WS_FindNextFileA_ex() takes a lastError out-parameter and carries
  the body of WS_FindNextFileA(), which now calls it with NULL. A
  failing return reports the FindNextFileW() error, or
  ERROR_NO_UNICODE_TRANSLATION when the name would not convert.
- FindNextDirEntry() calls WS_FindNextFileA_ex() on Windows. An
  ERROR_NO_MORE_FILES result frees ctx->entry, sets it to NULL and
  returns WS_NEXT_ERROR so the caller pops the directory; every other
  error still returns WS_FATAL_ERROR.

Issue: F-13316
pull/1245/head
Yosuke Shimizu 2026-09-08 11:37:59 +09:00 committed by John Safranek
parent e7a05229ad
commit 29762a64c6
3 changed files with 37 additions and 9 deletions

View File

@ -326,21 +326,35 @@ void* WS_FindFirstFileA(const char* fileName,
}
int WS_FindNextFileA(void* findHandle,
char* realFileName, size_t realFileNameSz)
int WS_FindNextFileA_ex(void* findHandle,
char* realFileName, size_t realFileNameSz, unsigned long* lastError)
{
BOOL success;
WIN32_FIND_DATAW findFileData;
errno_t error = 0;
unsigned long err = 0;
success = FindNextFileW((HANDLE)findHandle, &findFileData);
if (success) {
error = wcstombs_s(NULL, realFileName, realFileNameSz,
findFileData.cFileName, realFileNameSz);
if (wcstombs_s(NULL, realFileName, realFileNameSz,
findFileData.cFileName, realFileNameSz) != 0)
err = (unsigned long)ERROR_NO_UNICODE_TRANSLATION;
}
else {
err = (unsigned long)GetLastError();
}
return (success != 0) && (error == 0);
if (lastError != NULL)
*lastError = err;
return (success != 0) && (err == 0);
}
int WS_FindNextFileA(void* findHandle,
char* realFileName, size_t realFileNameSz)
{
return WS_FindNextFileA_ex(findHandle, realFileName, realFileNameSz, NULL);
}

View File

@ -3021,10 +3021,20 @@ static int FindNextDirEntry(void *fs, ScpSendCtx* ctx)
do {
char realFileName[MAX_PATH];
int sz;
unsigned long lastError;
if (WS_FindNextFileA(ctx->currentDir->dir,
realFileName, sizeof(realFileName)) == 0) {
return WS_FATAL_ERROR;
if (WS_FindNextFileA_ex(ctx->currentDir->dir,
realFileName, sizeof(realFileName), &lastError) == 0) {
if (lastError != ERROR_NO_MORE_FILES) {
return WS_FATAL_ERROR;
}
/* end of directory, leave entry NULL so the caller pops it */
if (ctx->entry != NULL) {
WFREE(ctx->entry, NULL, DYNTYPE_SCPDIR);
ctx->entry = NULL;
}
return WS_NEXT_ERROR;
}
sz = (int)WSTRLEN(realFileName);

View File

@ -580,6 +580,10 @@ extern "C" {
void* heap);
WOLFSSH_API int WS_FindNextFileA(void* findHandle,
char* realFileName, size_t realFileNameSz);
/* lastError is set on every return, 0 on success */
WOLFSSH_LOCAL int WS_FindNextFileA_ex(void* findHandle,
char* realFileName, size_t realFileNameSz,
unsigned long* lastError);
WOLFSSH_LOCAL int WS_GetFileAttributesExA(const char* fileName,
void* fileInfo, void* heap);
WOLFSSH_LOCAL int WS_RemoveDirectoryA(const char* dirName,