Missing API-calls for common structure fields make programing unduly difficult.
UnitedMarsupials opened this issue · comments
Describe the bug
A program to upload files over SFTP must go through several layers before it can start writing the data (using libssh2_sftp_write
):
- initialize and
connect
the socket - initialize
LIBSSH2_SESSION
-- and add the above socket to it (vialibssh2_session_handshake()
) - initialize
LIBSSH2_SFTP
with the above session (vialibssh2_sftp_init
) - initialize
LIBSSH2_SFTP_HANDLE
with the above pointer (vialibssh2_sftp_open_ex
)
Each layer creates an internal structure -- and returns an opaque pointer to it, which is Ok. However, various upper-level operations still require the lower-level identifiers. Currently the programmers must keep all of them in their own code in addition to them being kept inside libssh2's own internal structures:
- The
_LIBSSH2_SFTP_HANDLE
has a reference toLIBSSH2_SFTP
- The
_LIBSSH2_SFTP
has a reference to the underlyingLIBSSH2_SESSION
(via thechannel
-pointer) - The
_LIBSSH2_SESSION
keeps the associated socket recorded too -- thesocket_fd
-field
But there are no API-calls for a library-client to access any of this.
To Reproduce
The below snippet trying to analyze the result of a libssh2_sftp_mkdir
-call, for example, shows the need for both LIBSSH2_SFTP
and LIBSSH2_SESSION
pointers -- which must be kept around by the client on its own, despite already being recorded by the library:
e = libssh2_sftp_mkdir(sftp, dir,
LIBSSH2_SFTP_S_IRWXU|
LIBSSH2_SFTP_S_IRGRP|LIBSSH2_SFTP_S_IXGRP|
LIBSSH2_SFTP_S_IROTH|LIBSSH2_SFTP_S_IXOTH);
switch (e) {
case 0:
inform(2, "%s created", dir);
break;
case LIBSSH2_ERROR_SFTP_PROTOCOL:
e = libssh2_sftp_last_error(sftp);
if (e == LIBSSH2_FX_FILE_ALREADY_EXISTS)
inform(1, "%s was already there", dir);
else
inform(0, "Creating %s: SFTP-error %d, "
"ignoring", dir, e);
break;
default:
libssh2_session_last_error(session, &emsg, &elen, 0);
inform(1, "Creating %s: %.*s, ignoring",
dir, elen, emsg);
}
Another example is freeing-up/closing of an SFTP-transfer:
cleanup:
if (remote)
libssh2_sftp_close(remote);
libssh2_sftp_shutdown(sftp);
libssh2_session_disconnect(session, "Normal Shutdown");
libssh2_session_free(session);
close(socket);
return result;
Expected behavior
Access to those fields of the internal structures, that originated from the client-program anyway, should be accessible to the program via API-calls like:
int libssh2_session_getsocket(const LIBSSH2_SESSION *);
LIBSSH2_SESSION *libssh2_sftp_getsession(const LIBSSH2_SFTP *);
LIBSSH2_SFTP *libssh2_sftp_getsftp(const LIBSSH2_SFTP_HANDLE *);
Version (please complete the following information):
- OS and version: FreeBSD-13, RHEL7
- libssh2 version: 1.10.0, 1.8.0 respectively
- crypto backend and version: OpenSSL