mirror of
https://github.com/MidnightCommander/mc
synced 2025-03-12 19:03:10 +03:00
Merge branch '3406_sftp_error_31'
* 3406_sftp_error_31: (panel_operate_init_totals): fix directory size calculation. (panel_operate_init_totals): change the 'source' argument type... sftpfs: handle file operation errors. (sftpfs_close_file): return actual result of sftp file close operation. (sftpfs_waitsocket): refactor and use it for file and directory operations. Clarify usage of sftpfs_internal_stat() return value. sftpfs: refactoring: move initialization of sftp stat operations to separate function. sftpfs: refactoring: move initialization of sftp operation to separate function. (sftpfs_waitsocket): handle socket errors. sftpfs: refactoring: move handling of socket errors to separate function. (sftpfs_fstat): use sftpfs_attr_to_stat(). sftpfs: refactoring: move obtaining of stat info from sftp attributes to separate function. sftpfs: refactoring: move error check to separate function. Fix sftp error 31 (proto 4 and 2) sftp handle LIBSSH2_FX_PERMISSION_DENIED as EACCES. Ticket #3406: sftpfs: fix -31 SFTP Protocol Error when transferring file via SFTP Link.
This commit is contained in:
commit
79b6a772fe
@ -1325,7 +1325,8 @@ panel_compute_totals (const WPanel * panel, dirsize_status_msg_t * sm, size_t *
|
||||
|
||||
/** Initialize variables for progress bars */
|
||||
static FileProgressStatus
|
||||
panel_operate_init_totals (const WPanel * panel, const char *source, file_op_context_t * ctx,
|
||||
panel_operate_init_totals (const WPanel * panel, const vfs_path_t * source,
|
||||
const struct stat *source_stat, file_op_context_t * ctx,
|
||||
filegui_dialog_type_t dialog_type)
|
||||
{
|
||||
FileProgressStatus status;
|
||||
@ -1350,15 +1351,18 @@ panel_operate_init_totals (const WPanel * panel, const char *source, file_op_con
|
||||
if (source == NULL)
|
||||
status = panel_compute_totals (panel, &dsm, &ctx->progress_count, &ctx->progress_bytes,
|
||||
ctx->follow_links);
|
||||
else
|
||||
else if (S_ISDIR (source_stat->st_mode))
|
||||
{
|
||||
vfs_path_t *p;
|
||||
size_t dir_count = 0;
|
||||
|
||||
p = vfs_path_from_str (source);
|
||||
status = compute_dir_size (p, &dsm, &dir_count, &ctx->progress_count,
|
||||
status = compute_dir_size (source, &dsm, &dir_count, &ctx->progress_count,
|
||||
&ctx->progress_bytes, ctx->follow_links);
|
||||
vfs_path_free (p);
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx->progress_count++;
|
||||
ctx->progress_bytes += (uintmax_t) source_stat->st_size;
|
||||
status = FILE_CONT;
|
||||
}
|
||||
|
||||
status_msg_deinit (STATUS_MSG (&dsm));
|
||||
@ -2864,8 +2868,8 @@ panel_operate (void *source_panel, FileOperation operation, gboolean force_singl
|
||||
else
|
||||
source_with_vpath = vfs_path_append_new (panel->cwd_vpath, source, (char *) NULL);
|
||||
#endif /* WITH_FULL_PATHS */
|
||||
if (panel_operate_init_totals (panel, vfs_path_as_str (source_with_vpath), ctx, dialog_type)
|
||||
== FILE_CONT)
|
||||
if (panel_operate_init_totals (panel, source_with_vpath, &src_stat, ctx, dialog_type) ==
|
||||
FILE_CONT)
|
||||
{
|
||||
if (operation == OP_DELETE)
|
||||
{
|
||||
@ -2958,7 +2962,7 @@ panel_operate (void *source_panel, FileOperation operation, gboolean force_singl
|
||||
goto clean_up;
|
||||
}
|
||||
|
||||
if (panel_operate_init_totals (panel, NULL, ctx, dialog_type) == FILE_CONT)
|
||||
if (panel_operate_init_totals (panel, NULL, NULL, ctx, dialog_type) == FILE_CONT)
|
||||
{
|
||||
/* Loop for every file, perform the actual copy operation */
|
||||
for (i = 0; i < panel->dir.len; i++)
|
||||
|
@ -95,14 +95,8 @@ sftpfs_opendir (const vfs_path_t * vpath, GError ** mcerror)
|
||||
break;
|
||||
|
||||
libssh_errno = libssh2_session_last_errno (super_data->session);
|
||||
if (libssh_errno != LIBSSH2_ERROR_EAGAIN)
|
||||
{
|
||||
sftpfs_ssherror_to_gliberror (super_data, libssh_errno, mcerror);
|
||||
if (!sftpfs_waitsocket (super_data, libssh_errno, mcerror))
|
||||
return NULL;
|
||||
}
|
||||
sftpfs_waitsocket (super_data, mcerror);
|
||||
|
||||
mc_return_val_if_error (mcerror, NULL);
|
||||
}
|
||||
|
||||
sftpfs_dir = g_new0 (sftpfs_dir_data_t, 1);
|
||||
@ -138,14 +132,8 @@ sftpfs_readdir (void *data, GError ** mcerror)
|
||||
if (rc >= 0)
|
||||
break;
|
||||
|
||||
if (rc != LIBSSH2_ERROR_EAGAIN)
|
||||
{
|
||||
sftpfs_ssherror_to_gliberror (sftpfs_dir->super_data, rc, mcerror);
|
||||
if (!sftpfs_waitsocket (sftpfs_dir->super_data, rc, mcerror))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sftpfs_waitsocket (sftpfs_dir->super_data, mcerror);
|
||||
mc_return_val_if_error (mcerror, NULL);
|
||||
}
|
||||
while (rc == LIBSSH2_ERROR_EAGAIN);
|
||||
|
||||
@ -221,14 +209,8 @@ sftpfs_mkdir (const vfs_path_t * vpath, mode_t mode, GError ** mcerror)
|
||||
if (res >= 0)
|
||||
break;
|
||||
|
||||
if (res != LIBSSH2_ERROR_EAGAIN)
|
||||
{
|
||||
sftpfs_ssherror_to_gliberror (super_data, res, mcerror);
|
||||
if (!sftpfs_waitsocket (super_data, res, mcerror))
|
||||
return -1;
|
||||
}
|
||||
|
||||
sftpfs_waitsocket (super_data, mcerror);
|
||||
mc_return_val_if_error (mcerror, -1);
|
||||
}
|
||||
while (res == LIBSSH2_ERROR_EAGAIN);
|
||||
|
||||
@ -277,14 +259,8 @@ sftpfs_rmdir (const vfs_path_t * vpath, GError ** mcerror)
|
||||
if (res >= 0)
|
||||
break;
|
||||
|
||||
if (res != LIBSSH2_ERROR_EAGAIN)
|
||||
{
|
||||
sftpfs_ssherror_to_gliberror (super_data, res, mcerror);
|
||||
if (!sftpfs_waitsocket (super_data, res, mcerror))
|
||||
return -1;
|
||||
}
|
||||
|
||||
sftpfs_waitsocket (super_data, mcerror);
|
||||
mc_return_val_if_error (mcerror, -1);
|
||||
}
|
||||
while (res == LIBSSH2_ERROR_EAGAIN);
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <libssh2.h>
|
||||
#include <libssh2_sftp.h>
|
||||
|
||||
@ -49,6 +50,7 @@ typedef struct
|
||||
|
||||
/*** file scope variables ************************************************************************/
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/*** file scope functions ************************************************************************/
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/**
|
||||
@ -74,6 +76,23 @@ sftpfs_reopen (vfs_file_handler_t * file_handler, GError ** mcerror)
|
||||
sftpfs_open_file (file_handler, flags, mode, mcerror);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
sftpfs_file__handle_error (sftpfs_super_data_t * super_data, int sftp_res, GError ** mcerror)
|
||||
{
|
||||
if (sftpfs_is_sftp_error (super_data->sftp_session, sftp_res, LIBSSH2_FX_PERMISSION_DENIED))
|
||||
return -EACCES;
|
||||
|
||||
if (sftpfs_is_sftp_error (super_data->sftp_session, sftp_res, LIBSSH2_FX_NO_SUCH_FILE))
|
||||
return -ENOENT;
|
||||
|
||||
if (!sftpfs_waitsocket (super_data, sftp_res, mcerror))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/*** public functions ****************************************************************************/
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -204,46 +223,19 @@ sftpfs_fstat (void *data, struct stat *buf, GError ** mcerror)
|
||||
|
||||
do
|
||||
{
|
||||
int err;
|
||||
|
||||
res = libssh2_sftp_fstat_ex (sftpfs_fh->handle, &attrs, 0);
|
||||
if (res >= 0)
|
||||
break;
|
||||
|
||||
if (res != LIBSSH2_ERROR_EAGAIN)
|
||||
{
|
||||
sftpfs_ssherror_to_gliberror (super_data, res, mcerror);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sftpfs_waitsocket (super_data, mcerror);
|
||||
mc_return_val_if_error (mcerror, -1);
|
||||
err = sftpfs_file__handle_error (super_data, res, mcerror);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
while (res == LIBSSH2_ERROR_EAGAIN);
|
||||
|
||||
if ((attrs.flags & LIBSSH2_SFTP_ATTR_UIDGID) != 0)
|
||||
{
|
||||
buf->st_uid = attrs.uid;
|
||||
buf->st_gid = attrs.gid;
|
||||
}
|
||||
|
||||
if ((attrs.flags & LIBSSH2_SFTP_ATTR_ACMODTIME) != 0)
|
||||
{
|
||||
buf->st_atime = attrs.atime;
|
||||
buf->st_mtime = attrs.mtime;
|
||||
buf->st_ctime = attrs.mtime;
|
||||
#ifdef HAVE_STRUCT_STAT_ST_MTIM
|
||||
buf->st_atim.tv_nsec = buf->st_mtim.tv_nsec = buf->st_ctim.tv_nsec = 0;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
if ((attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) != 0)
|
||||
{
|
||||
buf->st_size = attrs.filesize;
|
||||
sftpfs_blksize (buf);
|
||||
}
|
||||
|
||||
if ((attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) != 0)
|
||||
buf->st_mode = attrs.permissions;
|
||||
sftpfs_attr_to_stat (&attrs, buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -281,18 +273,15 @@ sftpfs_read_file (vfs_file_handler_t * file_handler, char *buffer, size_t count,
|
||||
|
||||
do
|
||||
{
|
||||
int err;
|
||||
|
||||
rc = libssh2_sftp_read (file_handler_data->handle, buffer, count);
|
||||
if (rc >= 0)
|
||||
break;
|
||||
|
||||
if (rc != LIBSSH2_ERROR_EAGAIN)
|
||||
{
|
||||
sftpfs_ssherror_to_gliberror (super_data, rc, mcerror);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sftpfs_waitsocket (super_data, mcerror);
|
||||
mc_return_val_if_error (mcerror, -1);
|
||||
err = sftpfs_file__handle_error (super_data, (int) rc, mcerror);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
while (rc == LIBSSH2_ERROR_EAGAIN);
|
||||
|
||||
@ -331,18 +320,15 @@ sftpfs_write_file (vfs_file_handler_t * file_handler, const char *buffer, size_t
|
||||
|
||||
do
|
||||
{
|
||||
int err;
|
||||
|
||||
rc = libssh2_sftp_write (file_handler_data->handle, buffer, count);
|
||||
if (rc >= 0)
|
||||
break;
|
||||
|
||||
if (rc != LIBSSH2_ERROR_EAGAIN)
|
||||
{
|
||||
sftpfs_ssherror_to_gliberror (super_data, rc, mcerror);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sftpfs_waitsocket (super_data, mcerror);
|
||||
mc_return_val_if_error (mcerror, -1);
|
||||
err = sftpfs_file__handle_error (super_data, (int) rc, mcerror);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
while (rc == LIBSSH2_ERROR_EAGAIN);
|
||||
|
||||
@ -364,17 +350,18 @@ int
|
||||
sftpfs_close_file (vfs_file_handler_t * file_handler, GError ** mcerror)
|
||||
{
|
||||
sftpfs_file_handler_data_t *file_handler_data;
|
||||
int ret = -1;
|
||||
|
||||
mc_return_val_if_error (mcerror, -1);
|
||||
|
||||
file_handler_data = (sftpfs_file_handler_data_t *) file_handler->data;
|
||||
if (file_handler_data == NULL)
|
||||
return -1;
|
||||
if (file_handler_data != NULL)
|
||||
{
|
||||
ret = libssh2_sftp_close (file_handler_data->handle);
|
||||
g_free (file_handler_data);
|
||||
}
|
||||
|
||||
libssh2_sftp_close (file_handler_data->handle);
|
||||
|
||||
g_free (file_handler_data);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
@ -42,11 +42,156 @@ GString *sftpfs_filename_buffer = NULL;
|
||||
|
||||
/*** file scope variables ************************************************************************/
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/*** file scope functions ************************************************************************/
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* Adjust block size and number of blocks */
|
||||
|
||||
static void
|
||||
sftpfs_blksize (struct stat *s)
|
||||
{
|
||||
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
|
||||
s->st_blksize = LIBSSH2_CHANNEL_WINDOW_DEFAULT; /* FIXME */
|
||||
#endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */
|
||||
vfs_adjust_stat (s);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Awaiting for any activity on socket.
|
||||
*
|
||||
* @param super_data extra data for SFTP connection
|
||||
* @param mcerror pointer to the error object
|
||||
* @return 0 if success, negative value otherwise
|
||||
*/
|
||||
|
||||
static int
|
||||
sftpfs_internal_waitsocket (sftpfs_super_data_t * super_data, GError ** mcerror)
|
||||
{
|
||||
struct timeval timeout = { 10, 0 };
|
||||
fd_set fd;
|
||||
fd_set *writefd = NULL;
|
||||
fd_set *readfd = NULL;
|
||||
int dir, ret;
|
||||
|
||||
mc_return_val_if_error (mcerror, -1);
|
||||
|
||||
FD_ZERO (&fd);
|
||||
FD_SET (super_data->socket_handle, &fd);
|
||||
|
||||
/* now make sure we wait in the correct direction */
|
||||
dir = libssh2_session_block_directions (super_data->session);
|
||||
|
||||
if ((dir & LIBSSH2_SESSION_BLOCK_INBOUND) != 0)
|
||||
readfd = &fd;
|
||||
|
||||
if ((dir & LIBSSH2_SESSION_BLOCK_OUTBOUND) != 0)
|
||||
writefd = &fd;
|
||||
|
||||
ret = select (super_data->socket_handle + 1, readfd, writefd, NULL, &timeout);
|
||||
if (ret < 0)
|
||||
{
|
||||
int my_errno = errno;
|
||||
|
||||
mc_propagate_error (mcerror, my_errno, _("sftp: socket error: %s"),
|
||||
unix_error_string (my_errno));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static gboolean
|
||||
sftpfs_op_init (sftpfs_super_data_t ** super_data, const vfs_path_element_t ** path_element,
|
||||
const vfs_path_t * vpath, GError ** mcerror)
|
||||
{
|
||||
struct vfs_s_super *super = NULL;
|
||||
|
||||
mc_return_val_if_error (mcerror, FALSE);
|
||||
|
||||
if (vfs_s_get_path (vpath, &super, 0) == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (super == NULL)
|
||||
return FALSE;
|
||||
|
||||
*super_data = (sftpfs_super_data_t *) super->data;
|
||||
|
||||
if ((*super_data)->sftp_session == NULL)
|
||||
return FALSE;
|
||||
|
||||
*path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
sftpfs_stat_init (sftpfs_super_data_t ** super_data, const vfs_path_element_t ** path_element,
|
||||
const vfs_path_t * vpath, GError ** mcerror, int stat_type,
|
||||
LIBSSH2_SFTP_ATTRIBUTES * attrs)
|
||||
{
|
||||
int res;
|
||||
|
||||
if (!sftpfs_op_init (super_data, path_element, vpath, mcerror))
|
||||
return -1;
|
||||
|
||||
do
|
||||
{
|
||||
const char *fixfname;
|
||||
unsigned int fixfname_len;
|
||||
|
||||
fixfname = sftpfs_fix_filename ((*path_element)->path, &fixfname_len);
|
||||
|
||||
res = libssh2_sftp_stat_ex ((*super_data)->sftp_session, fixfname, fixfname_len,
|
||||
stat_type, attrs);
|
||||
if (res >= 0)
|
||||
break;
|
||||
|
||||
if (sftpfs_is_sftp_error ((*super_data)->sftp_session, res, LIBSSH2_FX_PERMISSION_DENIED))
|
||||
return -EACCES;
|
||||
|
||||
if (sftpfs_is_sftp_error ((*super_data)->sftp_session, res, LIBSSH2_FX_NO_SUCH_FILE))
|
||||
return -ENOENT;
|
||||
|
||||
if (!sftpfs_waitsocket (*super_data, res, mcerror))
|
||||
return -1;
|
||||
}
|
||||
while (res == LIBSSH2_ERROR_EAGAIN);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/*** public functions ****************************************************************************/
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
gboolean
|
||||
sftpfs_waitsocket (sftpfs_super_data_t * super_data, int sftp_res, GError ** mcerror)
|
||||
{
|
||||
if (sftp_res != LIBSSH2_ERROR_EAGAIN)
|
||||
{
|
||||
sftpfs_ssherror_to_gliberror (super_data, sftp_res, mcerror);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
sftpfs_internal_waitsocket (super_data, mcerror);
|
||||
|
||||
return (mcerror == NULL || *mcerror == NULL);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
gboolean
|
||||
sftpfs_is_sftp_error (LIBSSH2_SFTP * sftp_session, int sftp_res, int sftp_error)
|
||||
{
|
||||
return (sftp_res == LIBSSH2_ERROR_SFTP_PROTOCOL &&
|
||||
libssh2_sftp_last_error (sftp_session) == (unsigned long) sftp_error);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Convert libssh error to GError object.
|
||||
@ -65,7 +210,11 @@ sftpfs_ssherror_to_gliberror (sftpfs_super_data_t * super_data, int libssh_errno
|
||||
mc_return_if_error (mcerror);
|
||||
|
||||
libssh2_session_last_error (super_data->session, &err, &err_len, 1);
|
||||
mc_propagate_error (mcerror, libssh_errno, "%s", err);
|
||||
if (libssh_errno == LIBSSH2_ERROR_SFTP_PROTOCOL && super_data->sftp_session != NULL)
|
||||
mc_propagate_error (mcerror, libssh_errno, "%s %lu", err,
|
||||
libssh2_sftp_last_error (super_data->sftp_session));
|
||||
else
|
||||
mc_propagate_error (mcerror, libssh_errno, "%s", err);
|
||||
g_free (err);
|
||||
}
|
||||
|
||||
@ -88,51 +237,34 @@ sftpfs_fix_filename (const char *file_name, unsigned int *length)
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Awaiting for any activity on socket.
|
||||
*
|
||||
* @param super_data extra data for SFTP connection
|
||||
* @param mcerror pointer to the error object
|
||||
* @return 0 if success, negative value otherwise
|
||||
*/
|
||||
|
||||
int
|
||||
sftpfs_waitsocket (sftpfs_super_data_t * super_data, GError ** mcerror)
|
||||
{
|
||||
struct timeval timeout = { 10, 0 };
|
||||
fd_set fd;
|
||||
fd_set *writefd = NULL;
|
||||
fd_set *readfd = NULL;
|
||||
int dir;
|
||||
|
||||
mc_return_val_if_error (mcerror, -1);
|
||||
|
||||
FD_ZERO (&fd);
|
||||
FD_SET (super_data->socket_handle, &fd);
|
||||
|
||||
/* now make sure we wait in the correct direction */
|
||||
dir = libssh2_session_block_directions (super_data->session);
|
||||
|
||||
if ((dir & LIBSSH2_SESSION_BLOCK_INBOUND) != 0)
|
||||
readfd = &fd;
|
||||
|
||||
if ((dir & LIBSSH2_SESSION_BLOCK_OUTBOUND) != 0)
|
||||
writefd = &fd;
|
||||
|
||||
return select (super_data->socket_handle + 1, readfd, writefd, NULL, &timeout);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/* Adjust block size and number of blocks */
|
||||
|
||||
void
|
||||
sftpfs_blksize (struct stat *s)
|
||||
sftpfs_attr_to_stat (const LIBSSH2_SFTP_ATTRIBUTES * attrs, struct stat *s)
|
||||
{
|
||||
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
|
||||
s->st_blksize = LIBSSH2_CHANNEL_WINDOW_DEFAULT; /* FIXME */
|
||||
#endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */
|
||||
vfs_adjust_stat (s);
|
||||
if ((attrs->flags & LIBSSH2_SFTP_ATTR_UIDGID) != 0)
|
||||
{
|
||||
s->st_uid = attrs->uid;
|
||||
s->st_gid = attrs->gid;
|
||||
}
|
||||
|
||||
if ((attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME) != 0)
|
||||
{
|
||||
s->st_atime = attrs->atime;
|
||||
s->st_mtime = attrs->mtime;
|
||||
s->st_ctime = attrs->mtime;
|
||||
#ifdef HAVE_STRUCT_STAT_ST_MTIM
|
||||
s->st_atim.tv_nsec = s->st_mtim.tv_nsec = s->st_ctim.tv_nsec = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((attrs->flags & LIBSSH2_SFTP_ATTR_SIZE) != 0)
|
||||
{
|
||||
s->st_size = attrs->filesize;
|
||||
sftpfs_blksize (s);
|
||||
}
|
||||
|
||||
if ((attrs->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) != 0)
|
||||
s->st_mode = attrs->permissions;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -148,76 +280,19 @@ sftpfs_blksize (struct stat *s)
|
||||
int
|
||||
sftpfs_lstat (const vfs_path_t * vpath, struct stat *buf, GError ** mcerror)
|
||||
{
|
||||
struct vfs_s_super *super;
|
||||
sftpfs_super_data_t *super_data;
|
||||
sftpfs_super_data_t *super_data = NULL;
|
||||
const vfs_path_element_t *path_element = NULL;
|
||||
LIBSSH2_SFTP_ATTRIBUTES attrs;
|
||||
int res;
|
||||
const vfs_path_element_t *path_element;
|
||||
|
||||
mc_return_val_if_error (mcerror, -1);
|
||||
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
if (vfs_s_get_path (vpath, &super, 0) == NULL)
|
||||
return -1;
|
||||
|
||||
if (super == NULL)
|
||||
return -1;
|
||||
|
||||
super_data = (sftpfs_super_data_t *) super->data;
|
||||
if (super_data->sftp_session == NULL)
|
||||
return -1;
|
||||
|
||||
do
|
||||
res = sftpfs_stat_init (&super_data, &path_element, vpath, mcerror, LIBSSH2_SFTP_LSTAT, &attrs);
|
||||
if (res >= 0)
|
||||
{
|
||||
const char *fixfname;
|
||||
unsigned int fixfname_len = 0;
|
||||
|
||||
fixfname = sftpfs_fix_filename (path_element->path, &fixfname_len);
|
||||
|
||||
res =
|
||||
libssh2_sftp_stat_ex (super_data->sftp_session, fixfname, fixfname_len,
|
||||
LIBSSH2_SFTP_LSTAT, &attrs);
|
||||
if (res >= 0)
|
||||
break;
|
||||
|
||||
if (res != LIBSSH2_ERROR_EAGAIN)
|
||||
{
|
||||
sftpfs_ssherror_to_gliberror (super_data, res, mcerror);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sftpfs_waitsocket (super_data, mcerror);
|
||||
mc_return_val_if_error (mcerror, -1);
|
||||
}
|
||||
while (res == LIBSSH2_ERROR_EAGAIN);
|
||||
|
||||
if ((attrs.flags & LIBSSH2_SFTP_ATTR_UIDGID) != 0)
|
||||
{
|
||||
buf->st_uid = attrs.uid;
|
||||
buf->st_gid = attrs.gid;
|
||||
sftpfs_attr_to_stat (&attrs, buf);
|
||||
res = 0;
|
||||
}
|
||||
|
||||
if ((attrs.flags & LIBSSH2_SFTP_ATTR_ACMODTIME) != 0)
|
||||
{
|
||||
buf->st_atime = attrs.atime;
|
||||
buf->st_mtime = attrs.mtime;
|
||||
buf->st_ctime = attrs.mtime;
|
||||
#ifdef HAVE_STRUCT_STAT_ST_MTIM
|
||||
buf->st_atim.tv_nsec = buf->st_mtim.tv_nsec = buf->st_ctim.tv_nsec = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) != 0)
|
||||
{
|
||||
buf->st_size = attrs.filesize;
|
||||
sftpfs_blksize (buf);
|
||||
}
|
||||
|
||||
if ((attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) != 0)
|
||||
buf->st_mode = attrs.permissions;
|
||||
|
||||
return 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -233,77 +308,20 @@ sftpfs_lstat (const vfs_path_t * vpath, struct stat *buf, GError ** mcerror)
|
||||
int
|
||||
sftpfs_stat (const vfs_path_t * vpath, struct stat *buf, GError ** mcerror)
|
||||
{
|
||||
struct vfs_s_super *super;
|
||||
sftpfs_super_data_t *super_data;
|
||||
sftpfs_super_data_t *super_data = NULL;
|
||||
const vfs_path_element_t *path_element = NULL;
|
||||
LIBSSH2_SFTP_ATTRIBUTES attrs;
|
||||
int res;
|
||||
const vfs_path_element_t *path_element;
|
||||
|
||||
mc_return_val_if_error (mcerror, -1);
|
||||
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
if (vfs_s_get_path (vpath, &super, 0) == NULL)
|
||||
return -1;
|
||||
|
||||
if (super == NULL)
|
||||
return -1;
|
||||
|
||||
super_data = (sftpfs_super_data_t *) super->data;
|
||||
if (super_data->sftp_session == NULL)
|
||||
return -1;
|
||||
|
||||
do
|
||||
res = sftpfs_stat_init (&super_data, &path_element, vpath, mcerror, LIBSSH2_SFTP_STAT, &attrs);
|
||||
if (res >= 0)
|
||||
{
|
||||
const char *fixfname;
|
||||
unsigned int fixfname_len = 0;
|
||||
|
||||
fixfname = sftpfs_fix_filename (path_element->path, &fixfname_len);
|
||||
|
||||
res =
|
||||
libssh2_sftp_stat_ex (super_data->sftp_session, fixfname, fixfname_len,
|
||||
LIBSSH2_SFTP_STAT, &attrs);
|
||||
if (res >= 0)
|
||||
break;
|
||||
|
||||
if (res != LIBSSH2_ERROR_EAGAIN)
|
||||
{
|
||||
sftpfs_ssherror_to_gliberror (super_data, res, mcerror);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sftpfs_waitsocket (super_data, mcerror);
|
||||
mc_return_val_if_error (mcerror, -1);
|
||||
}
|
||||
while (res == LIBSSH2_ERROR_EAGAIN);
|
||||
|
||||
buf->st_nlink = 1;
|
||||
if ((attrs.flags & LIBSSH2_SFTP_ATTR_UIDGID) != 0)
|
||||
{
|
||||
buf->st_uid = attrs.uid;
|
||||
buf->st_gid = attrs.gid;
|
||||
buf->st_nlink = 1;
|
||||
sftpfs_attr_to_stat (&attrs, buf);
|
||||
res = 0;
|
||||
}
|
||||
|
||||
if ((attrs.flags & LIBSSH2_SFTP_ATTR_ACMODTIME) != 0)
|
||||
{
|
||||
buf->st_atime = attrs.atime;
|
||||
buf->st_mtime = attrs.mtime;
|
||||
buf->st_ctime = attrs.mtime;
|
||||
#ifdef HAVE_STRUCT_STAT_ST_MTIM
|
||||
buf->st_atim.tv_nsec = buf->st_mtim.tv_nsec = buf->st_ctim.tv_nsec = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) != 0)
|
||||
{
|
||||
buf->st_size = attrs.filesize;
|
||||
sftpfs_blksize (buf);
|
||||
}
|
||||
|
||||
if ((attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) != 0)
|
||||
buf->st_mode = attrs.permissions;
|
||||
|
||||
return 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -320,23 +338,11 @@ sftpfs_stat (const vfs_path_t * vpath, struct stat *buf, GError ** mcerror)
|
||||
int
|
||||
sftpfs_readlink (const vfs_path_t * vpath, char *buf, size_t size, GError ** mcerror)
|
||||
{
|
||||
struct vfs_s_super *super;
|
||||
sftpfs_super_data_t *super_data;
|
||||
sftpfs_super_data_t *super_data = NULL;
|
||||
const vfs_path_element_t *path_element = NULL;
|
||||
int res;
|
||||
const vfs_path_element_t *path_element;
|
||||
|
||||
mc_return_val_if_error (mcerror, -1);
|
||||
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
if (vfs_s_get_path (vpath, &super, 0) == NULL)
|
||||
return -1;
|
||||
|
||||
if (super == NULL)
|
||||
return -1;
|
||||
|
||||
super_data = (sftpfs_super_data_t *) super->data;
|
||||
if (super_data->sftp_session == NULL)
|
||||
if (!sftpfs_op_init (&super_data, &path_element, vpath, mcerror))
|
||||
return -1;
|
||||
|
||||
do
|
||||
@ -352,14 +358,8 @@ sftpfs_readlink (const vfs_path_t * vpath, char *buf, size_t size, GError ** mce
|
||||
if (res >= 0)
|
||||
break;
|
||||
|
||||
if (res != LIBSSH2_ERROR_EAGAIN)
|
||||
{
|
||||
sftpfs_ssherror_to_gliberror (super_data, res, mcerror);
|
||||
if (!sftpfs_waitsocket (super_data, res, mcerror))
|
||||
return -1;
|
||||
}
|
||||
|
||||
sftpfs_waitsocket (super_data, mcerror);
|
||||
mc_return_val_if_error (mcerror, -1);
|
||||
}
|
||||
while (res == LIBSSH2_ERROR_EAGAIN);
|
||||
|
||||
@ -379,26 +379,14 @@ sftpfs_readlink (const vfs_path_t * vpath, char *buf, size_t size, GError ** mce
|
||||
int
|
||||
sftpfs_symlink (const vfs_path_t * vpath1, const vfs_path_t * vpath2, GError ** mcerror)
|
||||
{
|
||||
struct vfs_s_super *super;
|
||||
sftpfs_super_data_t *super_data;
|
||||
sftpfs_super_data_t *super_data = NULL;
|
||||
const vfs_path_element_t *path_element1;
|
||||
const vfs_path_element_t *path_element2;
|
||||
const vfs_path_element_t *path_element2 = NULL;
|
||||
char *tmp_path;
|
||||
unsigned int tmp_path_len;
|
||||
int res;
|
||||
|
||||
mc_return_val_if_error (mcerror, -1);
|
||||
|
||||
path_element2 = vfs_path_get_by_index (vpath2, -1);
|
||||
|
||||
if (vfs_s_get_path (vpath2, &super, 0) == NULL)
|
||||
return -1;
|
||||
|
||||
if (super == NULL)
|
||||
return -1;
|
||||
|
||||
super_data = (sftpfs_super_data_t *) super->data;
|
||||
if (super_data->sftp_session == NULL)
|
||||
if (!sftpfs_op_init (&super_data, &path_element2, vpath2, mcerror))
|
||||
return -1;
|
||||
|
||||
tmp_path = (char *) sftpfs_fix_filename (path_element2->path, &tmp_path_len);
|
||||
@ -419,15 +407,7 @@ sftpfs_symlink (const vfs_path_t * vpath1, const vfs_path_t * vpath2, GError **
|
||||
if (res >= 0)
|
||||
break;
|
||||
|
||||
if (res != LIBSSH2_ERROR_EAGAIN)
|
||||
{
|
||||
sftpfs_ssherror_to_gliberror (super_data, res, mcerror);
|
||||
g_free (tmp_path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sftpfs_waitsocket (super_data, mcerror);
|
||||
if (mcerror != NULL && *mcerror != NULL)
|
||||
if (!sftpfs_waitsocket (super_data, res, mcerror))
|
||||
{
|
||||
g_free (tmp_path);
|
||||
return -1;
|
||||
@ -452,49 +432,14 @@ sftpfs_symlink (const vfs_path_t * vpath1, const vfs_path_t * vpath2, GError **
|
||||
int
|
||||
sftpfs_chmod (const vfs_path_t * vpath, mode_t mode, GError ** mcerror)
|
||||
{
|
||||
struct vfs_s_super *super;
|
||||
sftpfs_super_data_t *super_data;
|
||||
sftpfs_super_data_t *super_data = NULL;
|
||||
const vfs_path_element_t *path_element = NULL;
|
||||
LIBSSH2_SFTP_ATTRIBUTES attrs;
|
||||
int res;
|
||||
const vfs_path_element_t *path_element;
|
||||
|
||||
mc_return_val_if_error (mcerror, -1);
|
||||
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
if (vfs_s_get_path (vpath, &super, 0) == NULL)
|
||||
return -1;
|
||||
|
||||
if (super == NULL)
|
||||
return -1;
|
||||
|
||||
super_data = (sftpfs_super_data_t *) super->data;
|
||||
if (super_data->sftp_session == NULL)
|
||||
return -1;
|
||||
|
||||
do
|
||||
{
|
||||
const char *fixfname;
|
||||
unsigned int fixfname_len = 0;
|
||||
|
||||
fixfname = sftpfs_fix_filename (path_element->path, &fixfname_len);
|
||||
|
||||
res =
|
||||
libssh2_sftp_stat_ex (super_data->sftp_session, fixfname, fixfname_len,
|
||||
LIBSSH2_SFTP_LSTAT, &attrs);
|
||||
if (res >= 0)
|
||||
break;
|
||||
|
||||
if (res != LIBSSH2_ERROR_EAGAIN)
|
||||
{
|
||||
sftpfs_ssherror_to_gliberror (super_data, res, mcerror);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sftpfs_waitsocket (super_data, mcerror);
|
||||
mc_return_val_if_error (mcerror, -1);
|
||||
}
|
||||
while (res == LIBSSH2_ERROR_EAGAIN);
|
||||
res = sftpfs_stat_init (&super_data, &path_element, vpath, mcerror, LIBSSH2_SFTP_LSTAT, &attrs);
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
attrs.permissions = mode;
|
||||
|
||||
@ -511,16 +456,20 @@ sftpfs_chmod (const vfs_path_t * vpath, mode_t mode, GError ** mcerror)
|
||||
if (res >= 0)
|
||||
break;
|
||||
|
||||
if (res != LIBSSH2_ERROR_EAGAIN)
|
||||
if (sftpfs_is_sftp_error (super_data->sftp_session, res, LIBSSH2_FX_NO_SUCH_FILE))
|
||||
return -ENOENT;
|
||||
|
||||
if (sftpfs_is_sftp_error (super_data->sftp_session, res, LIBSSH2_FX_FAILURE))
|
||||
{
|
||||
sftpfs_ssherror_to_gliberror (super_data, res, mcerror);
|
||||
return -1;
|
||||
res = 0; /* need something like ftpfs_ignore_chattr_errors */
|
||||
break;
|
||||
}
|
||||
|
||||
sftpfs_waitsocket (super_data, mcerror);
|
||||
mc_return_val_if_error (mcerror, -1);
|
||||
if (!sftpfs_waitsocket (super_data, res, mcerror))
|
||||
return -1;
|
||||
}
|
||||
while (res == LIBSSH2_ERROR_EAGAIN);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -536,23 +485,11 @@ sftpfs_chmod (const vfs_path_t * vpath, mode_t mode, GError ** mcerror)
|
||||
int
|
||||
sftpfs_unlink (const vfs_path_t * vpath, GError ** mcerror)
|
||||
{
|
||||
struct vfs_s_super *super;
|
||||
sftpfs_super_data_t *super_data;
|
||||
sftpfs_super_data_t *super_data = NULL;
|
||||
const vfs_path_element_t *path_element = NULL;
|
||||
int res;
|
||||
const vfs_path_element_t *path_element;
|
||||
|
||||
mc_return_val_if_error (mcerror, -1);
|
||||
|
||||
path_element = vfs_path_get_by_index (vpath, -1);
|
||||
|
||||
if (vfs_s_get_path (vpath, &super, 0) == NULL)
|
||||
return -1;
|
||||
|
||||
if (super == NULL)
|
||||
return -1;
|
||||
|
||||
super_data = (sftpfs_super_data_t *) super->data;
|
||||
if (super_data->sftp_session == NULL)
|
||||
if (!sftpfs_op_init (&super_data, &path_element, vpath, mcerror))
|
||||
return -1;
|
||||
|
||||
do
|
||||
@ -566,14 +503,8 @@ sftpfs_unlink (const vfs_path_t * vpath, GError ** mcerror)
|
||||
if (res >= 0)
|
||||
break;
|
||||
|
||||
if (res != LIBSSH2_ERROR_EAGAIN)
|
||||
{
|
||||
sftpfs_ssherror_to_gliberror (super_data, res, mcerror);
|
||||
if (!sftpfs_waitsocket (super_data, res, mcerror))
|
||||
return -1;
|
||||
}
|
||||
|
||||
sftpfs_waitsocket (super_data, mcerror);
|
||||
mc_return_val_if_error (mcerror, -1);
|
||||
}
|
||||
while (res == LIBSSH2_ERROR_EAGAIN);
|
||||
|
||||
@ -593,25 +524,14 @@ sftpfs_unlink (const vfs_path_t * vpath, GError ** mcerror)
|
||||
int
|
||||
sftpfs_rename (const vfs_path_t * vpath1, const vfs_path_t * vpath2, GError ** mcerror)
|
||||
{
|
||||
struct vfs_s_super *super;
|
||||
sftpfs_super_data_t *super_data;
|
||||
sftpfs_super_data_t *super_data = NULL;
|
||||
const vfs_path_element_t *path_element1;
|
||||
const vfs_path_element_t *path_element2;
|
||||
const vfs_path_element_t *path_element2 = NULL;
|
||||
char *tmp_path;
|
||||
unsigned int tmp_path_len;
|
||||
int res;
|
||||
|
||||
mc_return_val_if_error (mcerror, -1);
|
||||
path_element2 = vfs_path_get_by_index (vpath2, -1);
|
||||
|
||||
if (vfs_s_get_path (vpath2, &super, 0) == NULL)
|
||||
return -1;
|
||||
|
||||
if (super == NULL)
|
||||
return -1;
|
||||
|
||||
super_data = (sftpfs_super_data_t *) super->data;
|
||||
if (super_data->sftp_session == NULL)
|
||||
if (!sftpfs_op_init (&super_data, &path_element2, vpath2, mcerror))
|
||||
return -1;
|
||||
|
||||
tmp_path = (char *) sftpfs_fix_filename (path_element2->path, &tmp_path_len);
|
||||
@ -632,15 +552,7 @@ sftpfs_rename (const vfs_path_t * vpath1, const vfs_path_t * vpath2, GError ** m
|
||||
if (res >= 0)
|
||||
break;
|
||||
|
||||
if (res != LIBSSH2_ERROR_EAGAIN)
|
||||
{
|
||||
sftpfs_ssherror_to_gliberror (super_data, res, mcerror);
|
||||
g_free (tmp_path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sftpfs_waitsocket (super_data, mcerror);
|
||||
if (mcerror != NULL && *mcerror != NULL)
|
||||
if (!sftpfs_waitsocket (super_data, res, mcerror))
|
||||
{
|
||||
g_free (tmp_path);
|
||||
return -1;
|
||||
|
@ -66,12 +66,13 @@ void sftpfs_init_subclass_callbacks (void);
|
||||
void sftpfs_init_config_variables_patterns (void);
|
||||
void sftpfs_deinit_config_variables_patterns (void);
|
||||
|
||||
gboolean sftpfs_is_sftp_error (LIBSSH2_SFTP * sftp_session, int sftp_res, int sftp_error);
|
||||
void sftpfs_ssherror_to_gliberror (sftpfs_super_data_t * super_data, int libssh_errno,
|
||||
GError ** mcerror);
|
||||
int sftpfs_waitsocket (sftpfs_super_data_t * super_data, GError ** mcerror);
|
||||
gboolean sftpfs_waitsocket (sftpfs_super_data_t * super_data, int sftp_res, GError ** mcerror);
|
||||
|
||||
const char *sftpfs_fix_filename (const char *file_name, unsigned int *length);
|
||||
void sftpfs_blksize (struct stat *s);
|
||||
void sftpfs_attr_to_stat (const LIBSSH2_SFTP_ATTRIBUTES * attrs, struct stat *s);
|
||||
int sftpfs_lstat (const vfs_path_t * vpath, struct stat *buf, GError ** mcerror);
|
||||
int sftpfs_stat (const vfs_path_t * vpath, struct stat *buf, GError ** mcerror);
|
||||
int sftpfs_readlink (const vfs_path_t * vpath, char *buf, size_t size, GError ** mcerror);
|
||||
|
Loading…
x
Reference in New Issue
Block a user