Skip to content

Commit ba2a9b9

Browse files
Merge pull request #725 from ejohnstown/scp-nonblock
Nonblocking SCP
2 parents e7ad7dd + 6a8f27c commit ba2a9b9

2 files changed

Lines changed: 82 additions & 44 deletions

File tree

src/wolfscp.c

Lines changed: 80 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1655,70 +1655,107 @@ int wolfSSH_SCP_connect(WOLFSSH* ssh, byte* cmd)
16551655
return ret;
16561656
}
16571657

1658-
static int wolfSSH_SCP_cmd(WOLFSSH* ssh, const char* localName,
1659-
const char* remoteName, byte dir)
1658+
1659+
static char* MakeScpCmd(const char* name, char dir, void* heap)
1660+
{
1661+
char* cmd;
1662+
int sz;
1663+
1664+
sz = WSNPRINTF(NULL, 0, "scp -%c %s", dir, name) + 1;
1665+
if (sz <= 0) {
1666+
return NULL;
1667+
}
1668+
cmd = (char*)WMALLOC(sz, heap, DYNTYPE_STRING);
1669+
if (cmd == NULL) {
1670+
return NULL;
1671+
}
1672+
sz = WSNPRINTF(cmd, sz, "scp -%c %s", dir, name);
1673+
if (sz <= 0) {
1674+
WFREE(cmd, heap, DYNTYPE_STRING);
1675+
return NULL;
1676+
}
1677+
1678+
return cmd;
1679+
}
1680+
1681+
1682+
int wolfSSH_SCP_to(WOLFSSH* ssh, const char* src, const char* dst)
16601683
{
1661-
char* cmd = NULL;
1662-
word32 remoteNameSz, cmdSz;
16631684
int ret = WS_SUCCESS;
16641685

1665-
if (ssh == NULL || localName == NULL || remoteName == NULL)
1666-
return WS_BAD_ARGUMENT;
1686+
/* dst is passed to the server in the scp -t command */
1687+
/* src is used locally to fopen and read for copy to */
16671688

1668-
if (dir != 't' && dir != 'f')
1689+
if (ssh == NULL || src == NULL || dst == NULL)
16691690
return WS_BAD_ARGUMENT;
16701691

1671-
remoteNameSz = (word32)WSTRLEN(remoteName);
1672-
cmdSz = remoteNameSz + (word32)WSTRLEN("scp -5 ") + 1;
1673-
cmd = (char*)WMALLOC(cmdSz, ssh->ctx->heap, DYNTYPE_STRING);
1674-
1675-
/* Need to set up the context for the local interaction callback. */
1692+
if (ssh->scpState == SCP_SETUP) {
1693+
char* cmd = MakeScpCmd(dst, 't', ssh->ctx->heap);
1694+
if (cmd == NULL) {
1695+
WLOG(WS_LOG_SCP, "Cannot allocate scp command");
1696+
ssh->error = WS_MEMORY_E;
1697+
return WS_ERROR;
1698+
}
16761699

1677-
if (cmd != NULL) {
1678-
WSNPRINTF(cmd, cmdSz, "scp -%c %s", dir, remoteName);
1679-
ssh->scpBasePath = localName;
1700+
ssh->scpBasePath = src;
16801701
ret = wolfSSH_SCP_connect(ssh, (byte*)cmd);
16811702
if (ret == WS_SUCCESS) {
1682-
if (dir == 't') {
1683-
ssh->scpState = SCP_SOURCE_BEGIN;
1684-
ssh->scpRequestState = SCP_SOURCE;
1685-
ret = DoScpSource(ssh);
1686-
}
1687-
else {
1688-
cmdSz = (word32)WSTRLEN(localName);
1689-
ret = ParseBasePathHelper(ssh, cmdSz);
1690-
if (ret == WS_SUCCESS) {
1691-
ssh->scpState = SCP_SINK_BEGIN;
1692-
ssh->scpRequestState = SCP_SINK;
1693-
ret = DoScpSink(ssh);
1694-
}
1695-
}
1703+
ssh->scpState = SCP_SOURCE_BEGIN;
1704+
ssh->scpRequestState = SCP_SOURCE;
1705+
}
1706+
if (cmd) {
1707+
WFREE(cmd, ssh->ctx->heap, DYNTYPE_STRING);
16961708
}
1697-
WFREE(cmd, ssh->ctx->heap, DYNTYPE_STRING);
16981709
}
1699-
else {
1700-
WLOG(WS_LOG_SCP, "Cannot build scp command");
1701-
ssh->error = WS_MEMORY_E;
1702-
ret = WS_ERROR;
1710+
if (ssh->scpState != SCP_SETUP) {
1711+
if (ret == WS_SUCCESS) {
1712+
ret = DoScpSource(ssh);
1713+
}
17031714
}
17041715

17051716
return ret;
17061717
}
17071718

17081719

1709-
int wolfSSH_SCP_to(WOLFSSH* ssh, const char* src, const char* dst)
1710-
{
1711-
return wolfSSH_SCP_cmd(ssh, src, dst, 't');
1712-
/* dst is passed to the server in the scp -t command */
1713-
/* src is used locally to fopen and read for copy to */
1714-
}
1715-
1716-
17171720
int wolfSSH_SCP_from(WOLFSSH* ssh, const char* src, const char* dst)
17181721
{
1719-
return wolfSSH_SCP_cmd(ssh, dst, src, 'f');
1722+
int ret = WS_SUCCESS;
1723+
17201724
/* src is passed to the server in the scp -f command */
17211725
/* dst is used locally to fopen and write for copy from */
1726+
1727+
if (ssh == NULL || src == NULL || dst == NULL)
1728+
return WS_BAD_ARGUMENT;
1729+
1730+
if (ssh->scpState == SCP_SETUP) {
1731+
char* cmd = MakeScpCmd(src, 'f', ssh->ctx->heap);
1732+
if (cmd == NULL) {
1733+
WLOG(WS_LOG_SCP, "Cannot allocate scp command");
1734+
ssh->error = WS_MEMORY_E;
1735+
return WS_ERROR;
1736+
}
1737+
1738+
ssh->scpBasePath = dst;
1739+
ret = wolfSSH_SCP_connect(ssh, (byte*)cmd);
1740+
if (ret == WS_SUCCESS) {
1741+
word32 srcSz = (word32)WSTRLEN(src);
1742+
ret = ParseBasePathHelper(ssh, srcSz);
1743+
}
1744+
if (ret == WS_SUCCESS) {
1745+
ssh->scpState = SCP_SINK_BEGIN;
1746+
ssh->scpRequestState = SCP_SINK;
1747+
}
1748+
if (cmd) {
1749+
WFREE(cmd, ssh->ctx->heap, DYNTYPE_STRING);
1750+
}
1751+
}
1752+
if (ssh->scpState != SCP_SETUP) {
1753+
if (ret == WS_SUCCESS) {
1754+
ret = DoScpSink(ssh);
1755+
}
1756+
}
1757+
1758+
return ret;
17221759
}
17231760
#endif /* ! NO_WOLFSSH_CLIENT */
17241761

wolfssh/internal.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1214,7 +1214,8 @@ enum WS_BufferTypes {
12141214
#define SCP_CONFIRM_FATAL 0x02 /* binary 2 */
12151215

12161216
enum WS_ScpStates {
1217-
SCP_PARSE_COMMAND = 0,
1217+
SCP_SETUP = 0,
1218+
SCP_PARSE_COMMAND,
12181219
SCP_SINK,
12191220
SCP_SINK_BEGIN,
12201221
SCP_TRANSFER,

0 commit comments

Comments
 (0)