cURL / Mailing Lists / curl-library / Single Mail

curl-library

Re: curl libssh2 sftp 4GB limit

From: <mikep_at_proatria.com>
Date: Thu, 6 Mar 2008 11:31:44 +0000

On Wed, Mar 05, 2008 at 09:55:21PM +0100, Daniel Stenberg wrote:
> I'm not aware of any such problems, assuming both libcurl and libssh2 are
> built with large file support. The LIBSSH2_SFTP_ATTRIBUTES struct even uses a
> libssh2_uint64_t type for the file size.
>
> Could it be a problem in the server end?
>
No - works with other clients

> > If anyone has any ideas please let me know (I will post to the libssh2 lists
> > and continue looking myself).
>
> You could start by trying one of the sftp examples in the libssh2 package and
> see if that shows the problem...
>

Good idea - the example sftp.c is a perfect starting place.

I've found the problem (I think) and it's related to the stat (which curl uses to determine download size) but the error is buried a bit deeper.

In libssh2 misc.c the function libssh2_ntohu64 seems to not correctly assign the return value (the bit shifting is fine). This may be a compliler issue, but I think it's easy to fix.

The replacement function is below. In summary, I think the act of multiplying an unsigned long is losing the part we need - probably needs a cast, but by using a simple assignment (to get the 64 bit value) then multiplying up the msl, before adding the lsl we get what we need. I realise this is libssh2 and not curl, but I thought it worth posting here as it tidies up the issue.

I'm not sure how this handles normal (big endian) machines - I assume it's not used in that case.

libssh2_uint64_t
libssh2_ntohu64(const unsigned char *buf)
{
   unsigned long lsl, msl;
   libssh2_uint64_t aval64; /* Used for return value */

   msl = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
   lsl = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
   aval64 = msl; /* No cast needed as 32 to 64 bit should work */
   aval64 = aval64 * 65536 * 65536; /* now force to correct value */
   aval64 = aval64 + lsl; /* add 32 to 64 bit should be ok */
   return aval64; /*was ((msl * 65536) * 65536) + lsl;*/
}

If you think this is a bug with the compiler then I'll raise on that side instead.

mikep_at_rockwell:~/src/libssh2/libssh2-0.18$ gcc -v
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --enable-languages=c,c++,fortran,objc,obj-c++,treelang --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --program-suffix=-4.1 --enable-__cxa_atexit --enable-clocale=gnu --enable-libstdcxx-debug --enable-mpfr --with-tune=i686 --enable-checking=release i486-linux-gnu
Thread model: posix
gcc version 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
mikep_at_rockwell:~/src/libssh2/libssh2-0.18$ uname -a
Linux rockwell 2.6.18-5-686 #1 SMP Wed Sep 26 17:54:59 UTC 2007 i686 GNU/Linux

-- 
Regards 
Mike Protts
Senior Technical Consultant
Pro:Atria Ltd
+44(0) 870 7656453
Received on 2008-03-06