SFTP: support '*' prefix for quote operations

prefixing a command with '*' means it is allowed to fail without
aborting the chain actions
This commit is contained in:
Jonas Schnelli 2011-11-18 15:55:09 +01:00 committed by Daniel Stenberg
parent 10ecdf5078
commit f64812ca63
4 changed files with 60 additions and 27 deletions

View File

@ -320,6 +320,7 @@ CURLOPT_DEBUGDATA 7.9.6
CURLOPT_DEBUGFUNCTION 7.9.6
CURLOPT_DIRLISTONLY 7.17.0
CURLOPT_DNS_CACHE_TIMEOUT 7.9.3
CURLOPT_DNS_SERVERS 7.24.0
CURLOPT_DNS_USE_GLOBAL_CACHE 7.9.3 7.11.1
CURLOPT_EGDSOCKET 7.7
CURLOPT_ENCODING 7.10

View File

@ -1063,7 +1063,20 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
/*
* Support some of the "FTP" commands
*/
if(curl_strequal("pwd", sshc->quote_item->data)) {
char *cmd = sshc->quote_item->data;
sshc->acceptfail = FALSE;
/* if a command starts with an asterisk, which a legal SFTP command never
can, the command will be allowed to fail without it causing any
aborts or cancels etc. It will cause libcurl to act as if the command
is successful, whatever the server reponds. */
if(cmd[0] == '*') {
cmd++;
sshc->acceptfail = TRUE;
}
if(curl_strequal("pwd", cmd)) {
/* output debug output if that is requested */
char *tmp = aprintf("257 \"%s\" is current directory.\n",
sftp_scp->path);
@ -1085,12 +1098,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
state(conn, SSH_SFTP_NEXT_QUOTE);
break;
}
else if(sshc->quote_item->data) {
else if(cmd) {
/*
* the arguments following the command must be separated from the
* command with a space so we can check for it unconditionally
*/
cp = strchr(sshc->quote_item->data, ' ');
cp = strchr(cmd, ' ');
if(cp == NULL) {
failf(data, "Syntax error in SFTP command. Supply parameter(s)!");
state(conn, SSH_SFTP_CLOSE);
@ -1121,9 +1134,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
* OpenSSH's sftp program and call the appropriate libssh2
* functions.
*/
if(curl_strnequal(sshc->quote_item->data, "chgrp ", 6) ||
curl_strnequal(sshc->quote_item->data, "chmod ", 6) ||
curl_strnequal(sshc->quote_item->data, "chown ", 6) ) {
if(curl_strnequal(cmd, "chgrp ", 6) ||
curl_strnequal(cmd, "chmod ", 6) ||
curl_strnequal(cmd, "chown ", 6) ) {
/* attribute change */
/* sshc->quote_path1 contains the mode to set */
@ -1146,8 +1159,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
state(conn, SSH_SFTP_QUOTE_STAT);
break;
}
else if(curl_strnequal(sshc->quote_item->data, "ln ", 3) ||
curl_strnequal(sshc->quote_item->data, "symlink ", 8)) {
else if(curl_strnequal(cmd, "ln ", 3) ||
curl_strnequal(cmd, "symlink ", 8)) {
/* symbolic linking */
/* sshc->quote_path1 is the source */
/* get the destination */
@ -1168,12 +1181,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
state(conn, SSH_SFTP_QUOTE_SYMLINK);
break;
}
else if(curl_strnequal(sshc->quote_item->data, "mkdir ", 6)) {
else if(curl_strnequal(cmd, "mkdir ", 6)) {
/* create dir */
state(conn, SSH_SFTP_QUOTE_MKDIR);
break;
}
else if(curl_strnequal(sshc->quote_item->data, "rename ", 7)) {
else if(curl_strnequal(cmd, "rename ", 7)) {
/* rename file */
/* first param is the source path */
/* second param is the dest. path */
@ -1193,12 +1206,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
state(conn, SSH_SFTP_QUOTE_RENAME);
break;
}
else if(curl_strnequal(sshc->quote_item->data, "rmdir ", 6)) {
else if(curl_strnequal(cmd, "rmdir ", 6)) {
/* delete dir */
state(conn, SSH_SFTP_QUOTE_RMDIR);
break;
}
else if(curl_strnequal(sshc->quote_item->data, "rm ", 3)) {
else if(curl_strnequal(cmd, "rm ", 3)) {
state(conn, SSH_SFTP_QUOTE_UNLINK);
break;
}
@ -1246,7 +1259,21 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
case SSH_SFTP_QUOTE_STAT:
if(!curl_strnequal(sshc->quote_item->data, "chmod", 5)) {
{
char *cmd = sshc->quote_item->data;
sshc->acceptfail = FALSE;
/* if a command starts with an asterisk, which a legal SFTP command never
can, the command will be allowed to fail without it causing any
aborts or cancels etc. It will cause libcurl to act as if the command
is successful, whatever the server reponds. */
if(cmd[0] == '*') {
cmd++;
sshc->acceptfail = TRUE;
}
if(!curl_strnequal(cmd, "chmod", 5)) {
/* Since chown and chgrp only set owner OR group but libssh2 wants to
* set them both at once, we need to obtain the current ownership
* first. This takes an extra protocol round trip.
@ -1258,7 +1285,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
else if(rc != 0) { /* get those attributes */
else if(rc != 0 && !sshc->acceptfail) { /* get those attributes */
err = (int)(libssh2_sftp_last_error(sshc->sftp_session));
Curl_safefree(sshc->quote_path1);
sshc->quote_path1 = NULL;
@ -1274,10 +1301,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
}
/* Now set the new attributes... */
if(curl_strnequal(sshc->quote_item->data, "chgrp", 5)) {
if(curl_strnequal(cmd, "chgrp", 5)) {
sshc->quote_attrs.gid = strtoul(sshc->quote_path1, NULL, 10);
sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
if(sshc->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0])) {
if(sshc->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
!sshc->acceptfail) {
Curl_safefree(sshc->quote_path1);
sshc->quote_path1 = NULL;
Curl_safefree(sshc->quote_path2);
@ -1289,7 +1317,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
}
else if(curl_strnequal(sshc->quote_item->data, "chmod", 5)) {
else if(curl_strnequal(cmd, "chmod", 5)) {
sshc->quote_attrs.permissions = strtoul(sshc->quote_path1, NULL, 8);
sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
/* permissions are octal */
@ -1306,10 +1334,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
}
else if(curl_strnequal(sshc->quote_item->data, "chown", 5)) {
else if(curl_strnequal(cmd, "chown", 5)) {
sshc->quote_attrs.uid = strtoul(sshc->quote_path1, NULL, 10);
sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
if(sshc->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0])) {
if(sshc->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
!sshc->acceptfail) {
Curl_safefree(sshc->quote_path1);
sshc->quote_path1 = NULL;
Curl_safefree(sshc->quote_path2);
@ -1325,6 +1354,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
/* Now send the completed structure... */
state(conn, SSH_SFTP_QUOTE_SETSTAT);
break;
}
case SSH_SFTP_QUOTE_SETSTAT:
rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
@ -1334,7 +1364,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
else if(rc != 0) {
else if(rc != 0 && !sshc->acceptfail) {
err = (int)(libssh2_sftp_last_error(sshc->sftp_session));
Curl_safefree(sshc->quote_path1);
sshc->quote_path1 = NULL;
@ -1359,7 +1389,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
else if(rc != 0) {
else if(rc != 0 && !sshc->acceptfail) {
err = (int)(libssh2_sftp_last_error(sshc->sftp_session));
Curl_safefree(sshc->quote_path1);
sshc->quote_path1 = NULL;
@ -1382,7 +1412,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
else if(rc != 0) {
else if(rc != 0 && !sshc->acceptfail) {
err = (int)(libssh2_sftp_last_error(sshc->sftp_session));
Curl_safefree(sshc->quote_path1);
sshc->quote_path1 = NULL;
@ -1407,7 +1437,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
else if(rc != 0) {
else if(rc != 0 && !sshc->acceptfail) {
err = (int)(libssh2_sftp_last_error(sshc->sftp_session));
Curl_safefree(sshc->quote_path1);
sshc->quote_path1 = NULL;
@ -1428,7 +1458,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
else if(rc != 0) {
else if(rc != 0 && !sshc->acceptfail) {
err = (int)(libssh2_sftp_last_error(sshc->sftp_session));
Curl_safefree(sshc->quote_path1);
sshc->quote_path1 = NULL;
@ -1447,7 +1477,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
else if(rc != 0) {
else if(rc != 0 && !sshc->acceptfail) {
err = (int)(libssh2_sftp_last_error(sshc->sftp_session));
Curl_safefree(sshc->quote_path1);
sshc->quote_path1 = NULL;

View File

@ -115,6 +115,7 @@ struct ssh_conn {
char *quote_path1; /* two generic pointers for the QUOTE stuff */
char *quote_path2;
LIBSSH2_SFTP_ATTRIBUTES quote_attrs; /* used by the SFTP_QUOTE state */
bool acceptfail; /* accept file in SFTP_QUOTE state */
char *homedir; /* when doing SFTP we figure out home dir in the
connect phase */

View File

@ -53,8 +53,9 @@ test600 test601 test602 test603 test604 \
test605 test606 test607 test608 test609 test610 test611 test612 test613 \
test614 test615 test616 test617 test618 test619 test620 test621 test622 \
test623 test624 test625 test626 test627 test628 test629 test630 test631 \
test632 test633 test634 test635 test636 test637 test700 test701 test702 \
test703 test704 test705 test706 test707 test708 test709 test710 \
test632 test633 test634 test635 test636 test637 test638 test639 \
test700 test701 test702 test703 test704 test705 test706 test707 test708 \
test709 test710 \
test800 test801 test802 \
test803 test804 test805 test806 test807 test808 test809 test810 test811 \
test812 test813 test814 \