libssh2_sftp_write(3)

πŸ“¦
version 1.11.1 Β· 3 versions
, in alpine 3.22, alpine 3.23, alpine 3.24, arch rolling, debian trixie, epel 10, epel 9, fedora 43, fedora 44, opensuse-leap 16.0, ubuntu questing, ubuntu resolute, ubuntu stonking

πŸ’– libssh2_sftp_write β€” write SFTP data πŸ’–

okay bestie, welcome to the libssh2 manual page for libssh2_sftp_write(3) β€” yes that's the whole name, it's giving very "function so nice they named it twice" energy, but it's literally just how man pages do πŸ’…


✨ SYNOPSIS ✨

#include <libssh2.h>
#include <libssh2_sftp.h>

ssize_t
libssh2_sftp_write(LIBSSH2_SFTP_HANDLE *handle,
                   const char *buffer,
                   size_t count);

🌸 DESCRIPTION 🌸

so libssh2_sftp_write(3) sends a whole block of data over to the SFTP server. it's modeled after the POSIX write() function and uses the exact same calling semantics β€” so if you already know write(), you already know her 🫢

  • handle β€” the SFTP file handle, as returned by libssh2_sftp_open_ex(3).
  • buffer β€” points to the data you're sending off into the void ✨
  • count β€” number of bytes from buffer to write. and here's the tea: it may not be possible to write all the bytes you asked for. rude, but true.

libssh2_sftp_handle(3) will use as much as possible of the buffer and shove it into a single SFTP protocol packet. which means: if you want maximum performance when you're sending larger files, you should try to always pass in at least 32K of data to this function. periodt. πŸ”₯


πŸ‘‘ WRITE AHEAD πŸ‘‘

starting in libssh2 version 1.2.8, the default behavior of libssh2 is to create several smaller outgoing packets for all the data you pass to this function, and it'll return a positive number as soon as the first packet gets acknowledged from the server. main character behavior honestly.

this has the effect that sometimes more data has been sent off but is not acked yet when this function returns β€” and when this function is subsequently called again to write more data, libssh2 will immediately figure out that the data is already received remotely. no cap.

in most normal situations this should not cause any problems, BUT (big but, bestie) it should be noted that if you have once called libssh2_sftp_write() with data and it returns short, you MUST still assume that the rest of the data might have been cached. so you need to make sure you do not alter that data and think that the version you have in your next function invoke will be detected or used. πŸ™ˆ

⚠️ fr fr: short return β‰  "the rest is safe to touch." the rest might already be cached. do not edit that buffer and assume your new version will be used. that's the trap.

the reason for this funny behavior is that SFTP can only send 32K data in each packet, and it gets all packets acked individually. this means we cannot use a simple serial approach if we want to reach high performance even on high latency connections. and we want that. πŸ’…


🌈 RETURN VALUE 🌈

  • actual number of bytes written β€” or negative on failure.
  • if used in non-blocking mode, it returns LIBSSH2_ERROR_EAGAIN when it would otherwise block. and while LIBSSH2_ERROR_EAGAIN is a negative number, it is not really a failure per se. it's just... vibing. 😌
  • if this function returns 0 (zero) it should not be considered an error β€” it just means there was no error, but yet no payload data got sent to the other end. zero bytes, zero drama. πŸŽ€

πŸ’€ ERRORS πŸ’€

  • LIBSSH2_ERROR_ALLOC β€” an internal memory allocation call failed. the malloc said "not today." 😭
  • LIBSSH2_ERROR_SOCKET_SEND β€” unable to send data on socket. the socket ghosted us.
  • LIBSSH2_ERROR_SOCKET_TIMEOUT β€”
  • LIBSSH2_ERROR_SFTP_PROTOCOL β€” an invalid SFTP protocol response was received on the socket, or an SFTP operation caused an errorcode to be returned by the server.

πŸ¦‹ SEE ALSO πŸ¦‹


okay that's the whole page bestie, you're officially SFTP-write literate, slay πŸ’œ and just so you know who to thank: this gem is from libssh2, version 0.15, dated 1 Jun 2007 β€” so yeah, she's vintage, she's iconic, she's been running the game longer than you've been alive (probably 😭) πŸŽ€βœ¨