diff --git a/doc/xml/release/2024/2.54.xml b/doc/xml/release/2024/2.54.xml index 621f3327f..84b08669d 100644 --- a/doc/xml/release/2024/2.54.xml +++ b/doc/xml/release/2024/2.54.xml @@ -104,6 +104,17 @@

Remove limitation on reading files in parallel during restore.

+ + + + + + + + + +

Improve SFTP error messages.

+
diff --git a/src/storage/sftp/storage.c b/src/storage/sftp/storage.c index 9b162409d..3eadb97ff 100644 --- a/src/storage/sftp/storage.c +++ b/src/storage/sftp/storage.c @@ -92,6 +92,113 @@ storageSftpKnownHostKeyType(const int hostKeyType) FUNCTION_TEST_RETURN(INT, result); } +/*********************************************************************************************************************************** +Return error message based on error code +***********************************************************************************************************************************/ +static const char * +libssh2SftpErrorMsg(const uint64_t error) +{ + FUNCTION_TEST_BEGIN(); + FUNCTION_TEST_PARAM(UINT64, error); + FUNCTION_TEST_END(); + + const char *result; + + // SFTP error status codes (returned by libssh2_sftp_last_error() + switch (error) + { + case LIBSSH2_FX_EOF: + result = "eof"; + break; + + case LIBSSH2_FX_NO_SUCH_FILE: + result = "no such file"; + break; + + case LIBSSH2_FX_PERMISSION_DENIED: + result = "permission denied"; + break; + + case LIBSSH2_FX_FAILURE: + result = "failure"; + break; + + case LIBSSH2_FX_BAD_MESSAGE: + result = "bad message"; + break; + + case LIBSSH2_FX_NO_CONNECTION: + result = "no connection"; + break; + + case LIBSSH2_FX_CONNECTION_LOST: + result = "connection lost"; + break; + + case LIBSSH2_FX_OP_UNSUPPORTED: + result = "operation unsupported"; + break; + + case LIBSSH2_FX_INVALID_HANDLE: + result = "invalid handle"; + break; + + case LIBSSH2_FX_NO_SUCH_PATH: + result = "no such path"; + break; + + case LIBSSH2_FX_FILE_ALREADY_EXISTS: + result = "file already exists"; + break; + + case LIBSSH2_FX_WRITE_PROTECT: + result = "write protect"; + break; + + case LIBSSH2_FX_NO_MEDIA: + result = "no media"; + break; + + case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM: + result = "no space on filesystem"; + break; + + case LIBSSH2_FX_QUOTA_EXCEEDED: + result = "quota exceeded"; + break; + + case LIBSSH2_FX_UNKNOWN_PRINCIPAL: + result = "unknown principal"; + break; + + case LIBSSH2_FX_LOCK_CONFLICT: + result = "lock conflict"; + break; + + case LIBSSH2_FX_DIR_NOT_EMPTY: + result = "directory not empty"; + break; + + case LIBSSH2_FX_NOT_A_DIRECTORY: + result = "not a directory"; + break; + + case LIBSSH2_FX_INVALID_FILENAME: + result = "invalid filename"; + break; + + case LIBSSH2_FX_LINK_LOOP: + result = "link loop"; + break; + + default: + result = "unknown error"; + break; + } + + FUNCTION_TEST_RETURN_CONST(STRINGZ, result); +} + /*********************************************************************************************************************************** Return a match failed message based on known host check failure type ***********************************************************************************************************************************/ @@ -301,7 +408,8 @@ storageSftpLibSsh2SessionFreeResource(THIS_VOID) THROW_FMT( ServiceError, "failed to shutdown sftpSession: libssh2 errno [%d]%s", rc, rc == LIBSSH2_ERROR_SFTP_PROTOCOL ? - strZ(strNewFmt(": sftp errno [%lu]", libssh2_sftp_last_error(this->sftpSession))) : ""); + strZ(strNewFmt(": sftp errno [%lu] %s", libssh2_sftp_last_error(this->sftpSession), + libssh2SftpErrorMsg(libssh2_sftp_last_error(this->sftpSession)))) : ""); else THROW_FMT( ServiceError, "timeout shutting down sftpSession: libssh2 errno [%d]", rc); @@ -363,7 +471,8 @@ storageSftpEvalLibSsh2Error( THROWP_FMT( errorType, "%s%s%s%s", message != NULL ? zNewFmt("%s%s", strZ(message), ssh2Errno == 0 ? "" : ": ") : "", ssh2Errno == 0 ? "" : zNewFmt("libssh2 error [%d]", ssh2Errno), - ssh2Errno == LIBSSH2_ERROR_SFTP_PROTOCOL ? zNewFmt(": sftp error [%" PRIu64 "]", sftpErrno) : "", + ssh2Errno == LIBSSH2_ERROR_SFTP_PROTOCOL ? + zNewFmt(": sftp error [%" PRIu64 "] %s", sftpErrno, libssh2SftpErrorMsg(sftpErrno)) : "", hint != NULL ? zNewFmt("\n%s", strZ(hint)) : ""); FUNCTION_TEST_NO_RETURN(); @@ -1011,8 +1120,8 @@ storageSftpPathRemove(THIS_VOID, const String *const path, const bool recurse, c else { THROW_FMT( - PathRemoveError, STORAGE_ERROR_PATH_REMOVE_FILE " libssh sftp [%" PRIu64 "]", strZ(file), - sftpErrno); + PathRemoveError, STORAGE_ERROR_PATH_REMOVE_FILE " libssh sftp [%" PRIu64 "] %s", strZ(file), + sftpErrno, libssh2SftpErrorMsg(sftpErrno)); } } else @@ -1046,7 +1155,11 @@ storageSftpPathRemove(THIS_VOID, const String *const path, const bool recurse, c const uint64_t sftpErrno = libssh2_sftp_last_error(this->sftpSession); if (sftpErrno != LIBSSH2_FX_NO_SUCH_FILE) - THROW_FMT(PathRemoveError, STORAGE_ERROR_PATH_REMOVE " sftp error [%" PRIu64 "]", strZ(path), sftpErrno); + { + THROW_FMT( + PathRemoveError, STORAGE_ERROR_PATH_REMOVE " sftp error [%" PRIu64 "] %s", strZ(path), sftpErrno, + libssh2SftpErrorMsg(sftpErrno)); + } // Path does not exist result = false; diff --git a/test/define.yaml b/test/define.yaml index 0684f151e..19d929a1b 100644 --- a/test/define.yaml +++ b/test/define.yaml @@ -626,7 +626,7 @@ unit: # ---------------------------------------------------------------------------------------------------------------------------- - name: sftp - total: 19 + total: 20 harness: name: libSsh2 integration: false diff --git a/test/src/module/storage/sftpTest.c b/test/src/module/storage/sftpTest.c index 3243b6f72..f739b8a70 100644 --- a/test/src/module/storage/sftpTest.c +++ b/test/src/module/storage/sftpTest.c @@ -2158,10 +2158,12 @@ testRun(void) TEST_ERROR_FMT( storageExistsP(storageTest, fileNoPerm), - FileOpenError, STORAGE_ERROR_INFO ": libssh2 error [-31]: sftp error [3]", strZ(fileNoPerm)); + FileOpenError, + STORAGE_ERROR_INFO ": libssh2 error [-31]: sftp error [3] permission denied", strZ(fileNoPerm)); TEST_ERROR_FMT( storagePathExistsP(storageTest, fileNoPerm), - FileOpenError, STORAGE_ERROR_INFO ": libssh2 error [-31]: sftp error [3]", strZ(fileNoPerm)); + FileOpenError, + STORAGE_ERROR_INFO ": libssh2 error [-31]: sftp error [3] permission denied", strZ(fileNoPerm)); // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("file and path"); @@ -2230,7 +2232,8 @@ testRun(void) TEST_ERROR_FMT( storageInfoP(storageTest, fileNoPerm), - FileOpenError, STORAGE_ERROR_INFO ": libssh2 error [-31]: sftp error [3]", strZ(fileNoPerm)); + FileOpenError, + STORAGE_ERROR_INFO ": libssh2 error [-31]: sftp error [3] permission denied", strZ(fileNoPerm)); memContextFree(objMemContext((StorageSftp *)storageDriver(storageTest))); @@ -2566,7 +2569,7 @@ testRun(void) // libssh2_sftp_symlink_ex fail link destination followLink false TEST_ERROR_FMT( storageInfoP(storageTest, linkName, .followLink = false), FileReadError, - "unable to get destination for link '" TEST_PATH "/testlink': libssh2 error [-31]: sftp error [21]"); + "unable to get destination for link '" TEST_PATH "/testlink': libssh2 error [-31]: sftp error [21] link loop"); // -------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("info - pipe"); @@ -2774,12 +2777,12 @@ testRun(void) TEST_ERROR_FMT( storageNewItrP(storageTest, pathNoPerm, .errorOnMissing = true), PathOpenError, - STORAGE_ERROR_LIST_INFO ": libssh2 error [-31]: sftp error [3]", strZ(pathNoPerm)); + STORAGE_ERROR_LIST_INFO ": libssh2 error [-31]: sftp error [3] permission denied", strZ(pathNoPerm)); // Should still error even when ignore missing TEST_ERROR_FMT( storageNewItrP(storageTest, pathNoPerm), PathOpenError, - STORAGE_ERROR_LIST_INFO ": libssh2 error [-31]: sftp error [3]", strZ(pathNoPerm)); + STORAGE_ERROR_LIST_INFO ": libssh2 error [-31]: sftp error [3] permission denied", strZ(pathNoPerm)); // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("helper function - storageSftpListEntry()"); @@ -3740,12 +3743,12 @@ testRun(void) TEST_ERROR_FMT( storageListP(storageTest, pathNoPerm, .errorOnMissing = true), PathOpenError, - STORAGE_ERROR_LIST_INFO ": libssh2 error [-31]: sftp error [3]", strZ(pathNoPerm)); + STORAGE_ERROR_LIST_INFO ": libssh2 error [-31]: sftp error [3] permission denied", strZ(pathNoPerm)); // Should still error even when ignore missing TEST_ERROR_FMT( storageListP(storageTest, pathNoPerm), PathOpenError, - STORAGE_ERROR_LIST_INFO ": libssh2 error [-31]: sftp error [3]", strZ(pathNoPerm)); + STORAGE_ERROR_LIST_INFO ": libssh2 error [-31]: sftp error [3] permission denied", strZ(pathNoPerm)); memContextFree(objMemContext((StorageSftp *)storageDriver(storageTest))); @@ -4125,7 +4128,7 @@ testRun(void) TEST_ERROR( storagePathCreateP(storageTest, STRDEF("sub3/sub4"), .noParentCreate = true), PathCreateError, - "sftp error unable to create path '" TEST_PATH "/sub3/sub4': libssh2 error [-31]: sftp error [2]"); + "sftp error unable to create path '" TEST_PATH "/sub3/sub4': libssh2 error [-31]: sftp error [2] no such file"); TEST_RESULT_VOID(storagePathCreateP(storageTest, STRDEF("sub3/sub4")), "create sub3/sub4"); // LIBSSH2_ERROR_EAGAIN timeout fail @@ -4184,7 +4187,7 @@ testRun(void) TEST_RESULT_VOID(storagePathCreateP(storageTest, STRDEF("subfail")), "timeout success"); TEST_ERROR( storagePathCreateP(storageTest, STRDEF("subfail"), .noParentCreate = true), PathCreateError, - "sftp error unable to create path '" TEST_PATH "/subfail': libssh2 error [-31]: sftp error [3]"); + "sftp error unable to create path '" TEST_PATH "/subfail': libssh2 error [-31]: sftp error [3] permission denied"); TEST_RESULT_VOID(storagePathCreateP(storageTest, STRDEF("subfail")), "do not throw error on already exists"); TEST_ERROR( storagePathCreateP(storageTest, STRDEF("subfail"), .errorOnExists = true), PathCreateError, @@ -4391,11 +4394,11 @@ testRun(void) // Mimic creation of pathRemove2 mode 700 TEST_ERROR_FMT( - storagePathRemoveP(storageTest, pathRemove2), PathRemoveError, STORAGE_ERROR_PATH_REMOVE " sftp error [3]", - strZ(pathRemove2)); + storagePathRemoveP(storageTest, pathRemove2), PathRemoveError, + STORAGE_ERROR_PATH_REMOVE " sftp error [3] permission denied", strZ(pathRemove2)); TEST_ERROR_FMT( storagePathRemoveP(storageTest, pathRemove2, .recurse = true), PathOpenError, - STORAGE_ERROR_LIST_INFO ": libssh2 error [-31]: sftp error [3]", strZ(pathRemove2)); + STORAGE_ERROR_LIST_INFO ": libssh2 error [-31]: sftp error [3] permission denied", strZ(pathRemove2)); // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("path remove - subpath permission denied"); @@ -4403,7 +4406,7 @@ testRun(void) // Mimic chmod 777 pathRemove1 TEST_ERROR_FMT( storagePathRemoveP(storageTest, pathRemove2, .recurse = true), PathOpenError, - STORAGE_ERROR_LIST_INFO ": libssh2 error [-31]: sftp error [3]", strZ(pathRemove2)); + STORAGE_ERROR_LIST_INFO ": libssh2 error [-31]: sftp error [3] permission denied", strZ(pathRemove2)); // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("path remove - file in subpath, permission denied"); @@ -4412,9 +4415,8 @@ testRun(void) // Mimic "sudo chmod 755 %s && sudo touch %s && sudo chmod 777 %s", strZ(pathRemove2), strZ(fileRemove), strZ(fileRemove)); TEST_ERROR_FMT( - storagePathRemoveP( - storageTest, pathRemove1, .recurse = true), PathRemoveError, STORAGE_ERROR_PATH_REMOVE " sftp error [3]", - strZ(pathRemove2)); + storagePathRemoveP(storageTest, pathRemove1, .recurse = true), PathRemoveError, + STORAGE_ERROR_PATH_REMOVE " sftp error [3] permission denied", strZ(pathRemove2)); // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("path remove - path with subpath and file removed"); @@ -4426,17 +4428,15 @@ testRun(void) TEST_TITLE("path remove - path with subpath ssh fail on unlink"); TEST_ERROR_FMT( - storagePathRemoveP( - storageTest, pathRemove1, .recurse = true), PathRemoveError, STORAGE_ERROR_PATH_REMOVE_FILE " libssh ssh [-7]", - strZ(pathRemove2)); + storagePathRemoveP(storageTest, pathRemove1, .recurse = true), PathRemoveError, + STORAGE_ERROR_PATH_REMOVE_FILE " libssh ssh [-7]", strZ(pathRemove2)); // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("path remove - other than LIBSSH2_FX_FAILURE/LIBSSH2_FX_PERMISSION_DENIED"); TEST_ERROR_FMT( - storagePathRemoveP( - storageTest, pathRemove1, .recurse = true), PathRemoveError, STORAGE_ERROR_PATH_REMOVE_FILE " libssh sftp [7]", - strZ(pathRemove2)); + storagePathRemoveP(storageTest, pathRemove1, .recurse = true), PathRemoveError, + STORAGE_ERROR_PATH_REMOVE_FILE " libssh sftp [7] connection lost", strZ(pathRemove2)); memContextFree(objMemContext((StorageSftp *)storageDriver(storageTest))); @@ -4958,7 +4958,7 @@ testRun(void) TEST_ASSIGN(file, storageNewWriteP(storageTest, fileNoPerm, .noAtomic = true, .noCreatePath = false), "new write file"); TEST_ERROR_FMT( ioWriteOpen(storageWriteIo(file)), FileOpenError, - STORAGE_ERROR_WRITE_OPEN ": libssh2 error [-31]: sftp error [3]", strZ(fileNoPerm)); + STORAGE_ERROR_WRITE_OPEN ": libssh2 error [-31]: sftp error [3] permission denied", strZ(fileNoPerm)); memContextFree(objMemContext((StorageSftp *)storageDriver(storageTest))); @@ -5270,7 +5270,8 @@ testRun(void) TEST_RESULT_INT(ioWriteFd(storageWriteIo(file)), -1, "check write fd"); TEST_ERROR_FMT( ioWriteClose(storageWriteIo(file)), FileCloseError, - "unable to move '%s' to '%s': libssh2 error [-31]: sftp error [7]", strZ(fileNameTmp), strZ(fileName)); + "unable to move '%s' to '%s': libssh2 error [-31]: sftp error [7] connection lost", strZ(fileNameTmp), + strZ(fileName)); memContextFree(objMemContext((StorageSftp *)storageDriver(storageTest))); @@ -5681,7 +5682,7 @@ testRun(void) {.function = HRNLIBSSH2_SESSION_BLOCK_DIRECTIONS, .resultInt = SSH2_NO_BLOCK_READING_WRITING}, {.function = HRNLIBSSH2_SFTP_UNLINK_EX, .param = "[\"" TEST_PATH "/test.empty\"]", .resultInt = LIBSSH2_ERROR_SFTP_PROTOCOL}, - {.function = HRNLIBSSH2_SFTP_LAST_ERROR, .resultUInt = LIBSSH2_FX_OK}, + {.function = HRNLIBSSH2_SFTP_LAST_ERROR, .resultUInt = 99}, HRNLIBSSH2_MACRO_SHUTDOWN() }); @@ -5698,7 +5699,7 @@ testRun(void) TEST_ERROR( storagePutP(storageNewWriteP(storageTest, emptyFile), NULL), FileRemoveError, - "unable to remove existing '" TEST_PATH "/test.empty': libssh2 error [-31]: sftp error [0]"); + "unable to remove existing '" TEST_PATH "/test.empty': libssh2 error [-31]: sftp error [99] unknown error"); memContextFree(objMemContext((StorageSftp *)storageDriver(storageTest))); @@ -6360,7 +6361,7 @@ testRun(void) .knownHosts = strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpKnownHost, repoIdx)), .write = true); TEST_ERROR(storageRemoveP(storageTest, STRDEF("missing"), .errorOnMissing = true), FileRemoveError, - "unable to remove '/missing': libssh2 error [-31]: sftp error [2]"); + "unable to remove '/missing': libssh2 error [-31]: sftp error [2] no such file"); memContextFree(objMemContext((StorageSftp *)storageDriver(storageTest))); @@ -6390,7 +6391,7 @@ testRun(void) .knownHosts = strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpKnownHost, repoIdx)), .write = true); TEST_ERROR(storageRemoveP(storageTest, STRDEF("missing")), FileRemoveError, - "unable to remove '/missing': libssh2 error [-31]: sftp error [7]"); + "unable to remove '/missing': libssh2 error [-31]: sftp error [7] connection lost"); memContextFree(objMemContext((StorageSftp *)storageDriver(storageTest))); @@ -6559,7 +6560,7 @@ testRun(void) TEST_ASSIGN(file, storageNewWriteP(storageTest, fileName, .noSyncFile = true), "storageWriteSftpOpen sftp error"); TEST_ERROR_FMT( ioWriteOpen(storageWriteIo(file)), FileOpenError, - STORAGE_ERROR_WRITE_OPEN ": libssh2 error [-31]: sftp error [3]", strZ(fileName)); + STORAGE_ERROR_WRITE_OPEN ": libssh2 error [-31]: sftp error [3] permission denied", strZ(fileName)); memContextFree(objMemContext((StorageSftp *)storageDriver(storageTest))); @@ -6659,7 +6660,7 @@ testRun(void) TEST_ERROR_FMT( ioReadOpen(storageReadIo(file)), FileOpenError, - STORAGE_ERROR_READ_OPEN ": libssh2 error [-31]: sftp error [3]", strZ(fileNoPerm)); + STORAGE_ERROR_READ_OPEN ": libssh2 error [-31]: sftp error [3] permission denied", strZ(fileNoPerm)); // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("file missing"); @@ -6902,7 +6903,8 @@ testRun(void) TEST_ASSIGN(file, storageNewWriteP(storageTest, fileNoPerm, .noAtomic = true), "new write file"); TEST_ERROR_FMT( ioWriteOpen(storageWriteIo(file)), - FileOpenError, STORAGE_ERROR_WRITE_OPEN ": libssh2 error [-31]: sftp error [3]", strZ(fileNoPerm)); + FileOpenError, STORAGE_ERROR_WRITE_OPEN ": libssh2 error [-31]: sftp error [3] permission denied", + strZ(fileNoPerm)); memContextFree(objMemContext((StorageSftp *)storageDriver(storageTest))); @@ -7663,6 +7665,7 @@ testRun(void) HRNLIBSSH2_MACRO_STARTUP(), {.function = HRNLIBSSH2_SFTP_SHUTDOWN, .resultInt = LIBSSH2_ERROR_SFTP_PROTOCOL}, {.function = HRNLIBSSH2_SFTP_LAST_ERROR, .resultUInt = LIBSSH2_FX_CONNECTION_LOST}, + {.function = HRNLIBSSH2_SFTP_LAST_ERROR, .resultUInt = LIBSSH2_FX_CONNECTION_LOST}, {.function = NULL}, }); @@ -7682,7 +7685,7 @@ testRun(void) TEST_ASSIGN(storageSftp, storageDriver(storageTest), "assign storage"); TEST_ERROR_FMT( memContextFree(objMemContext((StorageSftp *)storageDriver(storageTest))), ServiceError, - "failed to shutdown sftpSession: libssh2 errno [-31]: sftp errno [7]"); + "failed to shutdown sftpSession: libssh2 errno [-31]: sftp errno [7] connection lost"); // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("storageSftpLibSsh2SessionFreeResource() sftp shutdown failure EAGAIN"); @@ -7859,19 +7862,46 @@ testRun(void) LIBSSH2_ERROR_SFTP_PROTOCOL, 16, &FileRemoveError, strNewFmt("unable to move '%s' to '%s'", "BOGUS", "NOT BOGUS"), STRDEF("HINT")), FileRemoveError, - "unable to move 'BOGUS' to 'NOT BOGUS': libssh2 error [-31]: sftp error [16]\n" + "unable to move 'BOGUS' to 'NOT BOGUS': libssh2 error [-31]: sftp error [16] unknown principal\n" "HINT"); TEST_ERROR_FMT( storageSftpEvalLibSsh2Error( LIBSSH2_ERROR_SFTP_PROTOCOL, 16, &FileRemoveError, strNewFmt("unable to move '%s' to '%s'", "BOGUS", "NOT BOGUS"), NULL), - FileRemoveError, - "unable to move 'BOGUS' to 'NOT BOGUS': libssh2 error [-31]: sftp error [16]"); + FileRemoveError, "unable to move 'BOGUS' to 'NOT BOGUS': libssh2 error [-31]: sftp error [16] unknown principal"); TEST_ERROR_FMT( - storageSftpEvalLibSsh2Error( - LIBSSH2_ERROR_SFTP_PROTOCOL, 16, &FileRemoveError, NULL, NULL), - FileRemoveError, - "libssh2 error [-31]: sftp error [16]"); + storageSftpEvalLibSsh2Error(LIBSSH2_ERROR_SFTP_PROTOCOL, 16, &FileRemoveError, NULL, NULL), + FileRemoveError, "libssh2 error [-31]: sftp error [16] unknown principal"); +#else + TEST_LOG(PROJECT_NAME " not built with sftp support"); +#endif // HAVE_LIBSSH2 + } + + // ***************************************************************************************************************************** + if (testBegin("libssh2SftpErrorMsg()")) + { +#ifdef HAVE_LIBSSH2 + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("libssh2SftpErrorMsg()"); + + TEST_RESULT_Z(libssh2SftpErrorMsg(LIBSSH2_FX_EOF), "eof", "LIBSSH2_FX_EOF"); + TEST_RESULT_Z(libssh2SftpErrorMsg(LIBSSH2_FX_FAILURE), "failure", "LIBSSH2_FX_FAILURE"); + TEST_RESULT_Z(libssh2SftpErrorMsg(LIBSSH2_FX_BAD_MESSAGE), "bad message", "LIBSSH2_FX_BAD_MESSAGE"); + TEST_RESULT_Z(libssh2SftpErrorMsg(LIBSSH2_FX_NO_CONNECTION), "no connection", "LIBSSH2_FX_NO_CONNECTION"); + TEST_RESULT_Z(libssh2SftpErrorMsg(LIBSSH2_FX_OP_UNSUPPORTED), "operation unsupported", "LIBSSH2_FX_OP_UNSUPPORTED"); + TEST_RESULT_Z(libssh2SftpErrorMsg(LIBSSH2_FX_INVALID_HANDLE), "invalid handle", "LIBSSH2_FX_INVALID_HANDLE"); + TEST_RESULT_Z(libssh2SftpErrorMsg(LIBSSH2_FX_NO_SUCH_PATH), "no such path", "LIBSSH2_FX_NO_SUCH_PATH"); + TEST_RESULT_Z( + libssh2SftpErrorMsg(LIBSSH2_FX_FILE_ALREADY_EXISTS), "file already exists", "LIBSSH2_FX_FILE_ALREADY_EXISTS"); + TEST_RESULT_Z(libssh2SftpErrorMsg(LIBSSH2_FX_WRITE_PROTECT), "write protect", "LIBSSH2_FX_WRITE_PROTECT"); + TEST_RESULT_Z(libssh2SftpErrorMsg(LIBSSH2_FX_NO_MEDIA), "no media", "LIBSSH2_FX_NO_MEDIA"); + TEST_RESULT_Z( + libssh2SftpErrorMsg(LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM), "no space on filesystem", "LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM"); + TEST_RESULT_Z(libssh2SftpErrorMsg(LIBSSH2_FX_QUOTA_EXCEEDED), "quota exceeded", "LIBSSH2_FX_QUOTA_EXCEEDED"); + TEST_RESULT_Z(libssh2SftpErrorMsg(LIBSSH2_FX_LOCK_CONFLICT), "lock conflict", "LIBSSH2_FX_LOCK_CONFLICT"); + TEST_RESULT_Z(libssh2SftpErrorMsg(LIBSSH2_FX_DIR_NOT_EMPTY), "directory not empty", "LIBSSH2_FX_DIR_NOT_EMPTY"); + TEST_RESULT_Z(libssh2SftpErrorMsg(LIBSSH2_FX_NOT_A_DIRECTORY), "not a directory", "LIBSSH2_FX_NOT_A_DIRECTORY"); + TEST_RESULT_Z(libssh2SftpErrorMsg(LIBSSH2_FX_INVALID_FILENAME), "invalid filename", "LIBSSH2_FX_INVALID_FILENAME"); #else TEST_LOG(PROJECT_NAME " not built with sftp support"); #endif // HAVE_LIBSSH2