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:
Andrew Borodin 2017-12-28 10:25:24 +03:00
commit 79b6a772fe
5 changed files with 282 additions and 402 deletions

View File

@ -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++)

View File

@ -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);

View File

@ -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;
}
/* --------------------------------------------------------------------------------------------- */

View File

@ -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;

View File

@ -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);