1
0
mirror of https://github.com/libssh2/libssh2.git synced 2025-07-31 00:03:08 +03:00

sftp: add open functions with custom attribute support

Before this patch, libssh2 sent hardcoded `LIBSSH2_SFTP_ATTRIBUTES`
struct on handle open. This can be problematic on some special OS,
where the file size should be known on new file creation. I added
two new functions to resolve this issue.

Patch-by: @vajdaakos on github via #506

Changes compared to #506:
- drop attr size fixup in favour of #946.
- move `memcpy()` under the state where we need it.
- bump filename length type to `size_t`.
- fix filenames in documentation and other nits.

Closes #506
Closes #947
This commit is contained in:
Viktor Szakats
2023-04-13 11:34:11 +00:00
parent ec0feae792
commit bf85faaa92
5 changed files with 133 additions and 2 deletions

View File

@ -138,6 +138,8 @@ dist_man_MANS = \
libssh2_sftp_mkdir_ex.3 \
libssh2_sftp_open.3 \
libssh2_sftp_open_ex.3 \
libssh2_sftp_open_ex_r.3 \
libssh2_sftp_open_r.3 \
libssh2_sftp_opendir.3 \
libssh2_sftp_read.3 \
libssh2_sftp_readdir.3 \

View File

@ -0,0 +1,73 @@
.TH libssh2_sftp_open_ex_r 3 "10 Apr 2023" "libssh2 1.11.0" "libssh2 manual"
.SH NAME
libssh2_sftp_open_ex_r - open filehandle for file on SFTP.
.SH SYNOPSIS
.nf
#include <libssh2.h>
#include <libssh2_sftp.h>
LIBSSH2_SFTP_HANDLE *
libssh2_sftp_open_ex_r(LIBSSH2_SFTP *sftp, const char *filename,
size_t filename_len,
unsigned long flags,
long mode,
int open_type,
LIBSSH2_SFTP_ATTRIBUTES *attrs);
.fi
.SH DESCRIPTION
\fIsftp\fP - SFTP instance as returned by \fIlibssh2_sftp_init(3)\fP
\fIfilename\fP - Remote file/directory resource to open
\fIfilename_len\fP - Length of filename
\fIflags\fP - Any reasonable combination of the LIBSSH2_FXF_* constants:
.RS
.IP LIBSSH2_FXF_READ
Open the file for reading.
.IP LIBSSH2_FXF_WRITE
Open the file for writing. If both this and LIBSSH2_FXF_READ are specified,
the file is opened for both reading and writing.
.IP LIBSSH2_FXF_APPEND
Force all writes to append data at the end of the file.
.IP LIBSSH2_FXF_CREAT,
If this flag is specified, then a new file will be created if one does not
already exist (if LIBSSH2_FXF_TRUNC is specified, the new file will be
truncated to zero length if it previously exists)
.IP LIBSSH2_FXF_TRUNC
Forces an existing file with the same name to be truncated to zero length when
creating a file by specifying LIBSSH2_FXF_CREAT. LIBSSH2_FXF_CREAT MUST also
be specified if this flag is used.
.IP LIBSSH2_FXF_EXCL
Causes the request to fail if the named file already exists.
LIBSSH2_FXF_CREAT MUST also be specified if this flag is used.
.RE
\fImode\fP - POSIX file permissions to assign if the file is being newly
created. See the LIBSSH2_SFTP_S_* convenience defines in <libssh2_sftp.h>
\fIopen_type\fP - Either of LIBSSH2_SFTP_OPENFILE (to open a file) or
LIBSSH2_SFTP_OPENDIR (to open a directory).
\fIattrs\fP - Pointer to LIBSSH2_SFTP_ATTRIBUTES struct. See
libssh2_sftp_fstat_ex for detailed usage.
.SH RETURN VALUE
A pointer to the newly created LIBSSH2_SFTP_HANDLE instance or NULL on
failure.
.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_SOCKET_TIMEOUT\fP -
\fILIBSSH2_ERROR_SFTP_PROTOCOL\fP - An invalid SFTP protocol response was
received on the socket, or an SFTP operation caused an errorcode to be
returned by the server.
\fILIBSSH2_ERROR_EAGAIN\fP - Marked for non-blocking I/O but the call would
block.
.SH SEE ALSO
.BR libssh2_sftp_close_handle(3)
.BR libssh2_sftp_fstat_ex(3)

View File

@ -0,0 +1,23 @@
.TH libssh2_sftp_open_r 3 "10 Apr 2023" "libssh2 1.11.0" "libssh2 manual"
.SH NAME
libssh2_sftp_open_r - convenience macro for \fIlibssh2_sftp_open_ex_r(3)\fP calls
.SH SYNOPSIS
.nf
#include <libssh2.h>
#include <libssh2_sftp.h>
LIBSSH2_SFTP_HANDLE *
libssh2_sftp_open_r(LIBSSH2_SFTP *sftp, const char *filename,
unsigned long flags,
long mode,
LIBSSH2_SFTP_ATTRIBUTES *attrs);
.fi
.SH DESCRIPTION
This is a macro defined in a public libssh2 header file that is using the
underlying function \fIlibssh2_sftp_open_ex_r(3)\fP.
.SH RETURN VALUE
See \fIlibssh2_sftp_open_ex_r(3)\fP
.SH ERRORS
See \fIlibssh2_sftp_open_ex_r(3)\fP
.SH SEE ALSO
.BR libssh2_sftp_open_ex_r(3)

View File

@ -238,6 +238,17 @@ libssh2_sftp_open_ex(LIBSSH2_SFTP *sftp,
libssh2_sftp_open_ex((sftp), \
(path), (unsigned int)strlen(path), \
0, 0, LIBSSH2_SFTP_OPENDIR)
LIBSSH2_API LIBSSH2_SFTP_HANDLE *
libssh2_sftp_open_ex_r(LIBSSH2_SFTP *sftp,
const char *filename,
size_t filename_len,
unsigned long flags,
long mode, int open_type,
LIBSSH2_SFTP_ATTRIBUTES *attrs);
#define libssh2_sftp_open_r(sftp, filename, flags, mode, attrs) \
libssh2_sftp_open_ex_r((sftp), (filename), strlen(filename), \
(flags), (mode), LIBSSH2_SFTP_OPENFILE, \
(attrs))
LIBSSH2_API ssize_t libssh2_sftp_read(LIBSSH2_SFTP_HANDLE *handle,
char *buffer, size_t buffer_maxlen);

View File

@ -1107,7 +1107,7 @@ libssh2_sftp_shutdown(LIBSSH2_SFTP *sftp)
static LIBSSH2_SFTP_HANDLE *
sftp_open(LIBSSH2_SFTP *sftp, const char *filename,
size_t filename_len, uint32_t flags, long mode,
int open_type)
int open_type, LIBSSH2_SFTP_ATTRIBUTES *attrs_in)
{
LIBSSH2_CHANNEL *channel = sftp->channel;
LIBSSH2_SESSION *session = channel->session;
@ -1122,6 +1122,10 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename,
if(sftp->open_state == libssh2_NB_state_idle) {
sftp->last_errno = LIBSSH2_FX_OK;
if(attrs_in) {
memcpy(&attrs, attrs_in, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
}
/* packet_len(4) + packet_type(1) + request_id(4) + filename_len(4) +
flags(4) */
sftp->open_packet_len = (uint32_t)(filename_len + 13 +
@ -1331,7 +1335,25 @@ libssh2_sftp_open_ex(LIBSSH2_SFTP *sftp, const char *filename,
BLOCK_ADJUST_ERRNO(hnd, sftp->channel->session,
sftp_open(sftp, filename, filename_len, (uint32_t)flags,
mode, open_type));
mode, open_type, NULL));
return hnd;
}
/* libssh2_sftp_open_ex_r
*/
LIBSSH2_API LIBSSH2_SFTP_HANDLE *
libssh2_sftp_open_ex_r(LIBSSH2_SFTP *sftp, const char *filename,
size_t filename_len, unsigned long flags, long mode,
int open_type, LIBSSH2_SFTP_ATTRIBUTES *attrs)
{
LIBSSH2_SFTP_HANDLE *hnd;
if(!sftp)
return NULL;
BLOCK_ADJUST_ERRNO(hnd, sftp->channel->session,
sftp_open(sftp, filename, filename_len, (uint32_t)flags,
mode, open_type, attrs));
return hnd;
}