diff --git a/CHANGES b/CHANGES index c49db5768..30e9dbd25 100644 --- a/CHANGES +++ b/CHANGES @@ -8,6 +8,14 @@ Dan F (14 May 2007) - Added SFTP directory listing test case 613. +- Added support for quote commands before a transfer using SFTP and test + case 614. + +- Changed the post-quote commands to occur after the transferred file is + closed. + +- Allow SFTP quote commands chmod, chown, chgrp to set a value of 0. + Dan F (9 May 2007) - Kristian Gunstone fixed a problem where overwriting an uploaded file with sftp didn't truncate it first, which would corrupt the file if the new diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 26e199e2d..cc9053c87 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -16,6 +16,7 @@ This release includes the following changes: o uses less memory in non-pipelined use cases o CURLOPT_HTTP200ALIASES matched transfers assume HTTP 1.0 compliance o more than one test harness can run at the same time without conflict + o SFTP now supports quote commands before a transfer This release includes the following bugfixes: @@ -41,6 +42,7 @@ This release includes the following bugfixes: o connection cache growth in multi handles o better handling of out of memory conditions o overwriting an uploaded file with sftp now truncates it first + o SFTP quote commands chmod, chown, chgrp can now set a value of 0 This release includes the following known bugs: diff --git a/docs/curl.1 b/docs/curl.1 index 11b7fe530..fbe8155d1 100644 --- a/docs/curl.1 +++ b/docs/curl.1 @@ -897,17 +897,17 @@ file will not be read and used. See the \fI-K/--config\fP for details on the default config file search path. .IP "-Q/--quote " (FTP/SFTP) Send an arbitrary command to the remote FTP or SFTP server. Quote -commands are -sent BEFORE the transfer is taking place (just after the initial PWD command -to be exact). To make commands take place after a successful transfer, prefix -them with a dash '-' (only the latter is supported with SFTP). To make -commands get sent after libcurl has changed working directory, just -before the transfer command(s), prefix the command with '+'. You may -specify any amount of commands. If the server returns failure for one -of the commands, the entire operation will be aborted. You must send -syntactically correct FTP commands as RFC959 defines to FTP servers, or -one of the following commands (with appropriate arguments) to SFTP servers: -chgrp, chmod, chown, ln, mkdir, rename, rm, rmdir, symlink. +commands are sent BEFORE the transfer is taking place (just after the +initial PWD command in an FTP transfer, to be exact). To make commands +take place after a successful transfer, prefix them with a dash '-'. +To make commands get sent after libcurl has changed working directory, +just before the transfer command(s), prefix the command with '+' (this +is only supported for FTP). You may specify any number of commands. If +the server returns failure for one of the commands, the entire operation +will be aborted. You must send syntactically correct FTP commands as +RFC959 defines to FTP servers, or one of the following commands (with +appropriate arguments) to SFTP servers: chgrp, chmod, chown, ln, mkdir, +rename, rm, rmdir, symlink. This option can be used multiple times. .IP "--random-file " diff --git a/docs/libcurl/curl_easy_setopt.3 b/docs/libcurl/curl_easy_setopt.3 index 3c8c4596e..3c789dd70 100644 --- a/docs/libcurl/curl_easy_setopt.3 +++ b/docs/libcurl/curl_easy_setopt.3 @@ -839,19 +839,20 @@ address. Default FTP operations are passive, and thus won't use PORT. You disable PORT again and go back to using the passive version by setting this option to NULL. .IP CURLOPT_QUOTE -Pass a pointer to a linked list of FTP commands to pass to the server prior to -your ftp request. This will be done before any other FTP commands are issued -(even before the CWD command). The linked list should be a fully valid list of -'struct curl_slist' structs properly filled in. Use \fIcurl_slist_append(3)\fP -to append strings (commands) to the list, and clear the entire list afterwards -with \fIcurl_slist_free_all(3)\fP. Disable this operation again by setting a -NULL to this option. +Pass a pointer to a linked list of FTP or SFTP commands to pass to +the server prior to your ftp request. This will be done before any +other commands are issued (even before the CWD command for FTP). The +linked list should be a fully valid list of 'struct curl_slist' structs +properly filled in with text strings. Use \fIcurl_slist_append(3)\fP +to append strings (commands) to the list, and clear the entire list +afterwards with \fIcurl_slist_free_all(3)\fP. Disable this operation +again by setting a NULL to this option. .IP CURLOPT_POSTQUOTE -Pass a pointer to a linked list of FTP commands to pass to the server after -your ftp transfer request. The linked list should be a fully valid list of -struct curl_slist structs properly filled in as described for -\fICURLOPT_QUOTE\fP. Disable this operation again by setting a NULL to this -option. +Pass a pointer to a linked list of FTP or SFTP commands to pass to the +server after your ftp transfer request. The linked list should be a +fully valid list of struct curl_slist structs properly filled in as +described for \fICURLOPT_QUOTE\fP. Disable this operation again by +setting a NULL to this option. .IP CURLOPT_PREQUOTE Pass a pointer to a linked list of FTP commands to pass to the server after the transfer type is set. The linked list should be a fully valid list of diff --git a/lib/ssh.c b/lib/ssh.c index cf847ae4e..5bba63986 100644 --- a/lib/ssh.c +++ b/lib/ssh.c @@ -714,6 +714,14 @@ CURLcode Curl_sftp_do(struct connectdata *conn, bool *done) *done = TRUE; /* unconditionally */ + /* Send any quote commands */ + if(conn->data->set.quote) { + infof(conn->data, "Sending quote commands\n"); + res = sftp_sendquote(conn, conn->data->set.quote); + if (res != CURLE_OK) + return res; + } + if (data->set.upload) { /* * NOTE!!! libssh2 requires that the destination path is a full path @@ -980,17 +988,18 @@ CURLcode Curl_sftp_done(struct connectdata *conn, CURLcode status, Curl_safefree(sftp->homedir); sftp->homedir = NULL; - /* Before we shut down, see if there are any post-quote commands to send: */ - if(!status && !premature && conn->data->set.postquote) { - rc = sftp_sendquote(conn, conn->data->set.postquote); - } - if (sftp->sftp_handle) { if (libssh2_sftp_close(sftp->sftp_handle) < 0) { infof(conn->data, "Failed to close libssh2 file\n"); } } + /* Before we shut down, see if there are any post-quote commands to send: */ + if(!status && !premature && conn->data->set.postquote) { + infof(conn->data, "Sending postquote commands\n"); + rc = sftp_sendquote(conn, conn->data->set.postquote); + } + if (sftp->sftp_session) { if (libssh2_sftp_shutdown(sftp->sftp_session) < 0) { infof(conn->data, "Failed to stop libssh2 sftp subsystem\n"); @@ -1060,7 +1069,7 @@ get_pathname(const char **cpp, char **path) const char *cp = *cpp, *end; char quot; u_int i, j; - const char *WHITESPACE = " \t\r\n"; + static const char * const WHITESPACE = " \t\r\n"; cp += strspn(cp, WHITESPACE); if (!*cp) { @@ -1239,7 +1248,7 @@ static CURLcode sftp_sendquote(struct connectdata *conn, /* Now set the new attributes... */ if (curl_strnequal(item->data, "chgrp", 5)) { attrs.gid = strtol(path1, NULL, 10); - if (attrs.gid == 0) { + if (attrs.gid == 0 && !ISDIGIT(path1[0])) { free(path1); free(path2); failf(data, "Syntax error: chgrp gid not a number"); @@ -1248,7 +1257,7 @@ static CURLcode sftp_sendquote(struct connectdata *conn, } else if (curl_strnequal(item->data, "chmod", 5)) { attrs.permissions = strtol(path1, NULL, 8);/* permissions are octal */ - if (attrs.permissions == 0) { + if (attrs.permissions == 0 && !ISDIGIT(path1[0])) { free(path1); free(path2); failf(data, "Syntax error: chmod permissions not a number"); @@ -1257,7 +1266,7 @@ static CURLcode sftp_sendquote(struct connectdata *conn, } else if (curl_strnequal(item->data, "chown", 5)) { attrs.uid = strtol(path1, NULL, 10); - if (attrs.uid == 0) { + if (attrs.uid == 0 && !ISDIGIT(path1[0])) { free(path1); free(path2); failf(data, "Syntax error: chown uid not a number"); diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am index 1671c4fa3..e418d41e4 100644 --- a/tests/data/Makefile.am +++ b/tests/data/Makefile.am @@ -41,4 +41,4 @@ EXTRA_DIST = test1 test108 test117 test127 test20 test27 test34 test46 \ test603 test401 test402 test290 test291 test292 test293 test403 test404 \ test405 test604 test605 test606 test607 test608 test609 test294 test295 \ test296 test297 test298 test610 test611 test612 test406 test407 test408 \ - test409 test613 + test409 test613 test614 diff --git a/tests/data/test614 b/tests/data/test614 new file mode 100644 index 000000000..407e3e4a6 --- /dev/null +++ b/tests/data/test614 @@ -0,0 +1,49 @@ + + + +SFTP +pre-quote +directory + + + +# +# Server-side + + +d????????? N U U N ??? N NN:NN . +d????????? N U U N ??? N NN:NN .. +d????????? N U U N ??? N NN:NN asubdir +-r-?r-?r-? 1 U U 37 Jan 1 2000 plainfile.txt +-r-?r-?r-? 1 U U 47 Dec 31 2000 rofile.txt + + + +# +# Client-side + + +sftp + + +perl %SRCDIR/libtest/test613.pl prepare %PWD/log/test614.dir + + +SFTP pre-quote chmod + + +--key curl_client_key --pubkey curl_client_key.pub -u %USER: -Q "chmod 444 %PWD/log/test614.dir/plainfile.txt" sftp://%HOSTIP:%SSHPORT%PWD/log/test614.dir/ + + +perl %SRCDIR/libtest/test613.pl postprocess %PWD/log/test614.dir %PWD/log/curl614.out + + + +# +# Verify data after the test has been "shot" + + +disable + + +