From be9ee7095e2d5021985f57d88f5f889d3c2b9d8f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 17 Apr 2010 19:47:50 +0200 Subject: [PATCH] libssh2_scp_send64: added to API to provide large file transfers The previously existing libssh2_scp_send_ex() function has no way to send files that are larger than 'size_t' which on 32bit systems mean 4GB. This new API uses a libssh2_int64_t type and should thus on most modern systems be able to send enormous files. --- TODO | 5 ++-- docs/Makefile.am | 1 + docs/libssh2_scp_send64.3 | 49 ++++++++++++++++++++++++++++++++++++++ docs/libssh2_scp_send_ex.3 | 11 +++++++-- include/libssh2.h | 4 ++++ src/scp.c | 38 +++++++++++++++++++---------- 6 files changed, 92 insertions(+), 16 deletions(-) create mode 100644 docs/libssh2_scp_send64.3 diff --git a/TODO b/TODO index c5586487..3b1ae559 100644 --- a/TODO +++ b/TODO @@ -9,8 +9,6 @@ Things TODO lib, like when libssh2_session_last_error() is asked to return the string with 'want_buf' set to non-zero. -* Provide a libssh2_scp_send() API for files larger than 4GB (32bit size) - * Add more info to the man pages. * Decrease the number of mallocs. Everywhere. @@ -54,3 +52,6 @@ At next SONAME bump * remove the existing libssh2_knownhost_add() function and rename libssh2_knownhost_addc to become the new libssh2_knownhost_add instead + +* remove the existing libssh2_scp_send_ex() function and rename + libssh2_scp_send64 to become the new libssh2_scp_send instead. diff --git a/docs/Makefile.am b/docs/Makefile.am index 8e2a3f88..e37d5ef9 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -88,6 +88,7 @@ dist_man_MANS = \ libssh2_scp_recv.3 \ libssh2_scp_send.3 \ libssh2_scp_send_ex.3 \ + libssh2_scp_send64.3 \ libssh2_session_abstract.3 \ libssh2_session_block_directions.3 \ libssh2_session_callback_set.3 \ diff --git a/docs/libssh2_scp_send64.3 b/docs/libssh2_scp_send64.3 new file mode 100644 index 00000000..9ff587d3 --- /dev/null +++ b/docs/libssh2_scp_send64.3 @@ -0,0 +1,49 @@ +.\" $Id: libssh2_scp_send_ex.3,v 1.3 2009/03/17 10:34:27 bagder Exp $ +.\" +.TH libssh2_scp_send64 3 "17 Apr 2010" "libssh2 1.2.6" "libssh2 manual" +.SH NAME +libssh2_scp_send64 - Send a file via SCP +.SH SYNOPSIS +.nf +#include + +LIBSSH2_CHANNEL * +libssh2_scp_send64(LIBSSH2_SESSION *session, const char *path, int mode, + libssh2_uint64_t size, time_t mtime, time_t atime); +.SH DESCRIPTION +\fIsession\fP - Session instance as returned by +.BR libssh2_session_init_ex(3) + +\fIpath\fP - Full path and filename of file to transfer to. That is the remote +file name. + +\fImode\fP - File access mode to create file with + +\fIsize\fP - Size of file being transmitted (Must be known ahead of +time). Note that this needs to be passed on as variable type +libssh2_uint64_t. This type is 64 bit on modern operating systems and +compilers. + +\fImtime\fP - mtime to assign to file being created + +\fIatime\fP - atime to assign to file being created (Set this and +mtime to zero to instruct remote host to use current time). + +Send a file to the remote host via SCP. +.SH RETURN VALUE +Pointer to a newly allocated LIBSSH2_CHANNEL instance, or NULL on errors. + +.SH ERRORS +\fILIBSSH2_ERROR_ALLOC\fP - An internal memory allocation call failed. + +\fILIBSSH2_ERROR_SOCKET_SEND\fP - Unable to send data on socket. + +\fILIBSSH2_ERROR_SCP_PROTOCOL\fP - + +\fILIBSSH2_ERROR_EAGAIN\fP - Marked for non-blocking I/O but the call would +block. +.SH AVAILABILITY +This function was added in libssh2 1.2.6 and is meant to replace the former +\fIlibssh2_scp_send_ex(3)\fP function. +.SH SEE ALSO +.BR libssh2_channel_open_ex(3) diff --git a/docs/libssh2_scp_send_ex.3 b/docs/libssh2_scp_send_ex.3 index 589c8df8..f5e16439 100644 --- a/docs/libssh2_scp_send_ex.3 +++ b/docs/libssh2_scp_send_ex.3 @@ -4,11 +4,16 @@ .SH NAME libssh2_scp_send_ex - Send a file via SCP .SH SYNOPSIS +.nf #include LIBSSH2_CHANNEL * -libssh2_scp_send_ex(LIBSSH2_SESSION *session, const char *path, int mode, size_t size, long mtime, long atime); +libssh2_scp_send_ex(LIBSSH2_SESSION *session, const char *path, int mode, + size_t size, long mtime, long atime); .SH DESCRIPTION +This function has been deemed deprecated since libssh2 1.2.6. See +\fIlibssh2_scp_send64(3)\fP. + \fIsession\fP - Session instance as returned by .BR libssh2_session_init_ex(3) @@ -38,6 +43,8 @@ Pointer to a newly allocated LIBSSH2_CHANNEL instance, or NULL on errors. \fILIBSSH2_ERROR_EAGAIN\fP - Marked for non-blocking I/O but the call would block. - +.SH AVAILABILITY +This function was marked deprecated in libssh2 1.2.6 as + \fIlibssh2_scp_send64(3)\fP has been introduced to replace this function. .SH SEE ALSO .BR libssh2_channel_open_ex(3) diff --git a/include/libssh2.h b/include/libssh2.h index 6737c0c4..67a34cbc 100644 --- a/include/libssh2.h +++ b/include/libssh2.h @@ -710,6 +710,10 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_scp_send_ex(LIBSSH2_SESSION *session, const char *path, int mode, size_t size, long mtime, long atime); +LIBSSH2_API LIBSSH2_CHANNEL * +libssh2_scp_send64(LIBSSH2_SESSION *session, const char *path, int mode, + libssh2_int64_t size, time_t mtime, time_t atime); + #define libssh2_scp_send(session, path, mode, size) \ libssh2_scp_send_ex((session), (path), (mode), (size), 0, 0) diff --git a/src/scp.c b/src/scp.c index d7093fd0..7551c996 100644 --- a/src/scp.c +++ b/src/scp.c @@ -775,10 +775,9 @@ libssh2_scp_recv(LIBSSH2_SESSION *session, const char *path, struct stat * sb) */ static LIBSSH2_CHANNEL * scp_send(LIBSSH2_SESSION * session, const char *path, int mode, - size_t size, long mtime, long atime) + libssh2_int64_t size, time_t mtime, time_t atime) { int cmd_len; - unsigned const char *base; int rc; if (session->scpSend_state == libssh2_NB_state_idle) { @@ -879,8 +878,8 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode, /* Send mtime and atime to be used for file */ session->scpSend_response_len = snprintf((char *) session->scpSend_response, - LIBSSH2_SCP_RESPONSE_BUFLEN, "T%ld 0 %ld 0\n", mtime, - atime); + LIBSSH2_SCP_RESPONSE_BUFLEN, "T%ld 0 %ld 0\n", + mtime, atime); _libssh2_debug(session, LIBSSH2_TRACE_SCP, "Sent %s", session->scpSend_response); } @@ -931,17 +930,16 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode, if (session->scpSend_state == libssh2_NB_state_sent4) { /* Send mode, size, and basename */ - base = (unsigned char *) strrchr(path, '/'); - if (base) { + const char *base = strrchr(path, '/'); + if (base) base++; - } else { - base = (unsigned char *) path; - } + else + base = path; session->scpSend_response_len = snprintf((char *) session->scpSend_response, - LIBSSH2_SCP_RESPONSE_BUFLEN, "C0%o %lu %s\n", mode, - (unsigned long) size, base); + LIBSSH2_SCP_RESPONSE_BUFLEN, "C0%o %llu %s\n", mode, + size, base); _libssh2_debug(session, LIBSSH2_TRACE_SCP, "Sent %s", session->scpSend_response); @@ -1029,11 +1027,27 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode, /* * libssh2_scp_send_ex * - * Send a file using SCP + * Send a file using SCP. Old API. */ LIBSSH2_API LIBSSH2_CHANNEL * libssh2_scp_send_ex(LIBSSH2_SESSION *session, const char *path, int mode, size_t size, long mtime, long atime) +{ + LIBSSH2_CHANNEL *ptr; + BLOCK_ADJUST_ERRNO(ptr, session, + scp_send(session, path, mode, size, + (time_t)mtime, (time_t)atime)); + return ptr; +} + +/* + * libssh2_scp_send64 + * + * Send a file using SCP + */ +LIBSSH2_API LIBSSH2_CHANNEL * +libssh2_scp_send64(LIBSSH2_SESSION *session, const char *path, int mode, + libssh2_int64_t size, time_t mtime, time_t atime) { LIBSSH2_CHANNEL *ptr; BLOCK_ADJUST_ERRNO(ptr, session,