sshv2.c
资源名称:FTP总集.rar [点击查看]
上传用户:tjfeida
上传日期:2013-03-10
资源大小:1917k
文件大小:54k
源码类别:
Ftp客户端
开发平台:
Visual C++
- /*****************************************************************************/
- /* sshv2.c - functions that will use the sshv2 protocol */
- /* Copyright (C) 1998-2002 Brian Masney <masneyb@gftp.org> */
- /* */
- /* This program is free software; you can redistribute it and/or modify */
- /* it under the terms of the GNU General Public License as published by */
- /* the Free Software Foundation; either version 2 of the License, or */
- /* (at your option) any later version. */
- /* */
- /* This program is distributed in the hope that it will be useful, */
- /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
- /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
- /* GNU General Public License for more details. */
- /* */
- /* You should have received a copy of the GNU General Public License */
- /* along with this program; if not, write to the Free Software */
- /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA */
- /*****************************************************************************/
- #include "gftp.h"
- static const char cvsid[] = "$Id: sshv2.c,v 1.11 2002/11/23 14:34:25 masneyb Exp $";
- #define SSH_MAX_HANDLE_SIZE 256
- #define SSH_MAX_STRING_SIZE 34000
- typedef struct sshv2_attribs_tag
- {
- gint32 flags;
- gint64 size;
- gint32 uid;
- gint32 gid;
- gint32 perm;
- gint32 atime;
- gint32 mtime;
- } sshv2_attribs;
- typedef struct sshv2_message_tag
- {
- gint32 length;
- char command;
- char *buffer,
- *pos,
- *end;
- } sshv2_message;
- typedef struct sshv2_params_tag
- {
- char handle[SSH_MAX_HANDLE_SIZE + 4]; /* We'll encode the ID in here too */
- int handle_len,
- dont_log_status : 1; /* For uploading files */
- sshv2_message message;
- gint32 id,
- count;
- #ifdef G_HAVE_GINT64
- gint64 offset;
- #else
- gint32 offset;
- #endif
- char *read_buffer;
- } sshv2_params;
- #define SSH_MY_VERSION 3
- #define SSH_FXP_INIT 1
- #define SSH_FXP_VERSION 2
- #define SSH_FXP_OPEN 3
- #define SSH_FXP_CLOSE 4
- #define SSH_FXP_READ 5
- #define SSH_FXP_WRITE 6
- #define SSH_FXP_LSTAT 7
- #define SSH_FXP_FSTAT 8
- #define SSH_FXP_SETSTAT 9
- #define SSH_FXP_FSETSTAT 10
- #define SSH_FXP_OPENDIR 11
- #define SSH_FXP_READDIR 12
- #define SSH_FXP_REMOVE 13
- #define SSH_FXP_MKDIR 14
- #define SSH_FXP_RMDIR 15
- #define SSH_FXP_REALPATH 16
- #define SSH_FXP_STAT 17
- #define SSH_FXP_RENAME 18
- #define SSH_FXP_STATUS 101
- #define SSH_FXP_HANDLE 102
- #define SSH_FXP_DATA 103
- #define SSH_FXP_NAME 104
- #define SSH_FXP_ATTRS 105
- #define SSH_FXP_EXTENDED 200
- #define SSH_FXP_EXTENDED_REPLY 201
- #define SSH_FILEXFER_ATTR_SIZE 0x00000001
- #define SSH_FILEXFER_ATTR_UIDGID 0x00000002
- #define SSH_FILEXFER_ATTR_PERMISSIONS 0x00000004
- #define SSH_FILEXFER_ATTR_ACMODTIME 0x00000008
- #define SSH_FILEXFER_ATTR_EXTENDED 0x80000000
- #define SSH_FXF_READ 0x00000001
- #define SSH_FXF_WRITE 0x00000002
- #define SSH_FXF_APPEND 0x00000004
- #define SSH_FXF_CREAT 0x00000008
- #define SSH_FXF_TRUNC 0x00000010
- #define SSH_FXF_EXCL 0x00000020
- #define SSH_FX_OK 0
- #define SSH_FX_EOF 1
- #define SSH_FX_NO_SUCH_FILE 2
- #define SSH_FX_PERMISSION_DENIED 3
- #define SSH_FX_FAILURE 4
- #define SSH_FX_BAD_MESSAGE 5
- #define SSH_FX_NO_CONNECTION 6
- #define SSH_FX_CONNECTION_LOST 7
- #define SSH_FX_OP_UNSUPPORTED 8
- static void
- sshv2_log_command (gftp_request * request, gftp_logging_level level,
- char type, char *message, size_t length)
- {
- gint32 id, num, attr, stattype;
- char *descr, *pos, oldchar;
- sshv2_params * params;
- params = request->protocol_data;
- memcpy (&id, message, 4);
- id = ntohl (id);
- switch (type)
- {
- case SSH_FXP_INIT:
- request->logging_function (level, request->user_data,
- _("%d: Protocol Initializationn"), id);
- break;
- case SSH_FXP_VERSION:
- memcpy (&num, message, 4);
- num = ntohl (num);
- request->logging_function (level, request->user_data,
- _("%d: Protocol version %dn"), id, num);
- break;
- case SSH_FXP_OPEN:
- memcpy (&num, message + 4, 4);
- num = ntohl (num);
- pos = message + 12 + num - 1;
- oldchar = *pos;
- *pos = ' ';
- request->logging_function (level, request->user_data,
- _("%d: Open %sn"), id, message + 8);
- *pos = oldchar;
- break;
- case SSH_FXP_CLOSE:
- request->logging_function (level, request->user_data,
- _("%d: Closen"), id);
- case SSH_FXP_READ:
- case SSH_FXP_WRITE:
- break;
- case SSH_FXP_OPENDIR:
- request->logging_function (level, request->user_data,
- _("%d: Open Directory %sn"), id,
- message + 8);
- break;
- case SSH_FXP_READDIR:
- request->logging_function (level, request->user_data,
- _("%d: Read Directoryn"), id);
- break;
- case SSH_FXP_REMOVE:
- request->logging_function (level, request->user_data,
- _("%d: Remove file %sn"), id,
- message + 8);
- break;
- case SSH_FXP_MKDIR:
- request->logging_function (level, request->user_data,
- _("%d: Make directory %sn"), id,
- message + 8);
- break;
- case SSH_FXP_RMDIR:
- request->logging_function (level, request->user_data,
- _("%d: Remove directory %sn"), id,
- message + 8);
- break;
- case SSH_FXP_REALPATH:
- request->logging_function (level, request->user_data,
- _("%d: Realpath %sn"), id,
- message + 8);
- break;
- case SSH_FXP_ATTRS:
- request->logging_function (level, request->user_data,
- _("%d: File attributesn"), id);
- break;
- case SSH_FXP_STAT:
- request->logging_function (level, request->user_data,
- _("%d: Stat %sn"), id,
- message + 8);
- break;
- case SSH_FXP_SETSTAT:
- memcpy (&num, message + 4, 4);
- num = ntohl (num);
- pos = message + 12 + num - 1;
- oldchar = *pos;
- *pos = ' ';
- memcpy (&stattype, message + 8 + num, 4);
- stattype = ntohl (stattype);
- memcpy (&attr, message + 12 + num, 4);
- attr = ntohl (attr);
- switch (stattype)
- {
- case SSH_FILEXFER_ATTR_PERMISSIONS:
- request->logging_function (level, request->user_data,
- _("%d: Chmod %s %on"), id,
- message + 8, attr);
- break;
- case SSH_FILEXFER_ATTR_ACMODTIME:
- request->logging_function (level, request->user_data,
- _("%d: Utime %s %dn"), id,
- message + 8, attr);
- }
- *pos = oldchar;
- break;
- case SSH_FXP_STATUS:
- if (params->dont_log_status)
- break;
- memcpy (&num, message + 4, 4);
- num = ntohl (num);
- switch (num)
- {
- case SSH_FX_OK:
- descr = _("OK");
- break;
- case SSH_FX_EOF:
- descr = _("EOF");
- break;
- case SSH_FX_NO_SUCH_FILE:
- descr = _("No such file or directory");
- break;
- case SSH_FX_PERMISSION_DENIED:
- descr = _("Permission denied");
- break;
- case SSH_FX_FAILURE:
- descr = _("Failure");
- break;
- case SSH_FX_BAD_MESSAGE:
- descr = _("Bad message");
- break;
- case SSH_FX_NO_CONNECTION:
- descr = _("No connection");
- break;
- case SSH_FX_CONNECTION_LOST:
- descr = _("Connection lost");
- break;
- case SSH_FX_OP_UNSUPPORTED:
- descr = _("Operation unsupported");
- break;
- default:
- descr = _("Unknown message returned from server");
- break;
- }
- request->logging_function (level, request->user_data,
- "%d: %sn", id, descr);
- break;
- case SSH_FXP_HANDLE:
- request->logging_function (level, request->user_data,
- "%d: File handlen", id);
- break;
- case SSH_FXP_DATA:
- break;
- case SSH_FXP_NAME:
- memcpy (&num, message + 4, 4);
- num = ntohl (num);
- request->logging_function (level, request->user_data,
- "%d: Filenames (%d entries)n", id,
- num);
- break;
- default:
- request->logging_function (level, request->user_data,
- "Command: %xn", type);
- }
- }
- static int
- sshv2_send_command (gftp_request * request, char type, char *command,
- gint32 len)
- {
- char buf[34000];
- gint32 clen;
- if (len > 33995)
- {
- request->logging_function (gftp_logging_error, request->user_data,
- _("Error: Message size %d too bign"), len);
- gftp_disconnect (request);
- return (-1);
- }
- clen = htonl (len + 1);
- memcpy (buf, &clen, 4);
- buf[4] = type;
- memcpy (&buf[5], command, len);
- buf[len + 5] = ' ';
- #ifdef DEBUG
- printf ("rSending: ");
- for (clen=0; clen<len + 5; clen++)
- printf ("%x ", buf[clen] & 0xff);
- printf ("n");
- #endif
- sshv2_log_command (request, gftp_logging_send, type, buf + 5, len);
- if (gftp_write (request, buf, len + 5, request->sockfd) < 0)
- return (-2);
- return 0;
- }
- static int
- sshv2_read_response (gftp_request * request, sshv2_message * message,
- int fd)
- {
- ssize_t numread, rem;
- char buf[5], *pos;
- if (fd <= 0)
- fd = request->sockfd;
- pos = buf;
- rem = 5;
- while (rem > 0)
- {
- if ((numread = gftp_read (request, pos, rem, fd)) < 0)
- return (-2);
- rem -= numread;
- pos += numread;
- }
- memcpy (&message->length, buf, 4);
- message->length = ntohl (message->length);
- if (message->length > 34000)
- {
- request->logging_function (gftp_logging_error, request->user_data,
- _("Error: Message size %d too big from servern"),
- message->length);
- memset (message, 0, sizeof (*message));
- gftp_disconnect (request);
- return (-1);
- }
- message->command = buf[4];
- message->buffer = g_malloc (message->length + 1);
- message->pos = message->buffer;
- message->end = message->buffer + message->length - 1;
- pos = message->buffer;
- rem = message->length - 1;
- while (rem > 0)
- {
- if ((numread = gftp_read (request, pos, rem, fd)) < 0)
- return (-2);
- rem -= numread;
- pos += numread;
- }
- message->buffer[message->length] = ' ';
- sshv2_log_command (request, gftp_logging_recv, message->command,
- message->buffer, message->length);
- return (message->command);
- }
- static void
- sshv2_destroy (gftp_request * request)
- {
- g_return_if_fail (request != NULL);
- g_return_if_fail (request->protonum == GFTP_SSHV2_NUM);
- g_free (request->protocol_data);
- request->protocol_data = NULL;
- }
- static void
- sshv2_message_free (sshv2_message * message)
- {
- if (message->buffer)
- g_free (message->buffer);
- memset (message, 0, sizeof (*message));
- }
- static gint32
- sshv2_buffer_get_int32 (gftp_request * request, sshv2_message * message,
- int expected_response)
- {
- gint32 ret;
- if (message->end - message->pos < 4)
- {
- request->logging_function (gftp_logging_error, request->user_data,
- _("Received wrong response from server, disconnectingn"));
- sshv2_message_free (message);
- gftp_disconnect (request);
- return (-2);
- }
- memcpy (&ret, message->pos, 4);
- ret = ntohl (ret);
- message->pos += 4;
- if (expected_response > 0 && ret != expected_response)
- {
- request->logging_function (gftp_logging_error, request->user_data,
- _("Received wrong response from server, disconnectingn"));
- sshv2_message_free (message);
- gftp_disconnect (request);
- return (-2);
- }
- return (ret);
- }
- static char *
- sshv2_buffer_get_string (gftp_request * request, sshv2_message * message)
- {
- char *string;
- gint32 len;
- if ((len = sshv2_buffer_get_int32 (request, message, -1)) < 0)
- return (NULL);
- if (len > SSH_MAX_STRING_SIZE || (message->end - message->pos < len))
- {
- request->logging_function (gftp_logging_error, request->user_data,
- _("Received wrong response from server, disconnectingn"));
- sshv2_message_free (message);
- gftp_disconnect (request);
- return (NULL);
- }
- string = g_malloc (len + 1);
- memcpy (string, message->pos, len);
- string[len] = ' ';
- message->pos += len;
- return (string);
- }
- static int
- sshv2_getcwd (gftp_request * request)
- {
- sshv2_message message;
- sshv2_params * params;
- char *tempstr, *dir;
- gint32 num;
- size_t len;
- int ret;
- g_return_val_if_fail (request != NULL, -2);
- g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2);
- if (request->directory == NULL || *request->directory == ' ')
- dir = ".";
- else
- dir = request->directory;
- params = request->protocol_data;
- len = strlen (dir);
- tempstr = g_malloc (len + 9);
- strcpy (tempstr + 8, dir);
- num = htonl (params->id++);
- memcpy (tempstr, &num, 4);
- num = htonl (len);
- memcpy (tempstr + 4, &num, 4);
- if (sshv2_send_command (request, SSH_FXP_REALPATH, tempstr, len + 8) < 0)
- {
- g_free (tempstr);
- return (-2);
- }
- g_free (tempstr);
- if (request->directory)
- {
- g_free (request->directory);
- request->directory = NULL;
- }
- memset (&message, 0, sizeof (message));
- ret = sshv2_read_response (request, &message, -1);
- if (ret == SSH_FXP_STATUS)
- {
- sshv2_message_free (&message);
- return (-2);
- }
- else if (ret != SSH_FXP_NAME)
- {
- request->logging_function (gftp_logging_error, request->user_data,
- _("Received wrong response from server, disconnectingn"));
- sshv2_message_free (&message);
- gftp_disconnect (request);
- return (-2);
- }
- message.pos += 4;
- if (sshv2_buffer_get_int32 (request, &message, 1) < 0)
- return (-2);
- if ((request->directory = sshv2_buffer_get_string (request, &message)) == NULL)
- return (-2);
- sshv2_message_free (&message);
- return (0);
- }
- static int
- sshv2_connect (gftp_request * request)
- {
- char **args, *tempstr, pts_name[20], *p1, p2, *exepath, port[6];
- int version, fdm, fds, s[2];
- sshv2_message message;
- pid_t child;
- g_return_val_if_fail (request != NULL, -2);
- g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2);
- g_return_val_if_fail (request->hostname != NULL, -2);
- if (request->sockfd > 0)
- return (0);
- request->logging_function (gftp_logging_misc, request->user_data,
- _("Opening SSH connection to %sn"),
- request->hostname);
- /* Ugh!! We don't get a login banner from sftp-server, and if we are
- using ssh-agent to cache a users password, then we won't receive
- any initial text from the server, and we'll block. So I just send a
- xsftp server banner over. I hope this works on most Unices */
- if (request->sftpserv_path == NULL ||
- *request->sftpserv_path == ' ')
- {
- p1 = "";
- p2 = ' ';
- }
- else
- {
- p1 = request->sftpserv_path;
- p2 = '/';
- }
- *port = ' ';
- exepath = g_strdup_printf ("echo -n xsftp ; %s%csftp-server", p1, p2);
- args = make_ssh_exec_args (request, exepath, sshv2_use_sftp_subsys, port);
- if (ssh_use_askpass || sshv2_use_sftp_subsys)
- {
- fdm = fds = 0;
- if (socketpair (AF_LOCAL, SOCK_STREAM, 0, s) < 0)
- {
- request->logging_function (gftp_logging_error, request->user_data,
- _("Cannot create a socket pair: %sn"),
- g_strerror (errno));
- return (-2);
- }
- }
- else
- {
- s[0] = s[1] = 0;
- if ((fdm = ptym_open (pts_name)) < 0)
- {
- request->logging_function (gftp_logging_error, request->user_data,
- _("Cannot open master pty %s: %sn"), pts_name,
- g_strerror (errno));
- return (-2);
- }
- }
- if ((child = fork ()) == 0)
- {
- setsid ();
- if (ssh_use_askpass || sshv2_use_sftp_subsys)
- {
- close (s[0]);
- fds = s[1];
- }
- else
- {
- if ((fds = ptys_open (fdm, pts_name)) < 0)
- {
- printf ("Cannot open slave pts %s: %sn", pts_name,
- g_strerror (errno));
- return (-1);
- }
- close (fdm);
- }
- tty_raw (fds);
- dup2 (fds, 0);
- dup2 (fds, 1);
- dup2 (fds, 2);
- if (!ssh_use_askpass && fds > 2)
- close (fds);
- execvp (ssh_prog_name != NULL && *ssh_prog_name != ' ' ?
- ssh_prog_name : "ssh", args);
- printf (_("Error: Cannot execute ssh: %sn"), g_strerror (errno));
- return (-1);
- }
- else if (child > 0)
- {
- if (ssh_use_askpass || sshv2_use_sftp_subsys)
- {
- close (s[1]);
- fdm = s[0];
- }
- tty_raw (fdm);
- if (!sshv2_use_sftp_subsys)
- {
- tempstr = ssh_start_login_sequence (request, fdm);
- if (!tempstr ||
- !(strlen (tempstr) > 4 && strcmp (tempstr + strlen (tempstr) - 5,
- "xsftp") == 0))
- {
- g_free (args);
- g_free (exepath);
- return (-2);
- }
- g_free (tempstr);
- }
- g_free (args);
- g_free (exepath);
- request->sockfd = fdm;
- version = htonl (SSH_MY_VERSION);
- if (sshv2_send_command (request, SSH_FXP_INIT, (char *) &version, 4) < 0)
- return (-2);
- memset (&message, 0, sizeof (message));
- if (sshv2_read_response (request, &message, -1) != SSH_FXP_VERSION)
- {
- request->logging_function (gftp_logging_error, request->user_data,
- _("Received wrong response from server, disconnectingn"));
- sshv2_message_free (&message);
- gftp_disconnect (request);
- return (-2);
- }
- sshv2_message_free (&message);
- request->logging_function (gftp_logging_misc, request->user_data,
- _("Successfully logged into SSH server %sn"),
- request->hostname);
- }
- else
- {
- request->logging_function (gftp_logging_error, request->user_data,
- _("Cannot fork another process: %sn"),
- g_strerror (errno));
- g_free (args);
- return (-1);
- }
- if (sshv2_getcwd (request) < 0)
- {
- if (request->directory)
- g_free (request->directory);
- request->directory = g_strdup (".");
- if (sshv2_getcwd (request) < 0)
- {
- gftp_disconnect (request);
- return (-2);
- }
- }
- return (0);
- }
- static void
- sshv2_disconnect (gftp_request * request)
- {
- sshv2_params * params;
- g_return_if_fail (request != NULL);
- g_return_if_fail (request->protonum == GFTP_SSHV2_NUM);
- params = request->protocol_data;
- if (request->sockfd > 0)
- {
- request->logging_function (gftp_logging_misc, request->user_data,
- _("Disconnecting from site %sn"),
- request->hostname);
- if (close (request->sockfd) < 0)
- request->logging_function (gftp_logging_error, request->user_data,
- _("Error closing file descriptor: %sn"),
- g_strerror (errno));
- request->sockfd = -1;
- }
- if (params->message.buffer != NULL)
- sshv2_message_free (¶ms->message);
- }
- static int
- sshv2_end_transfer (gftp_request * request)
- {
- sshv2_params * params;
- sshv2_message message;
- gint32 len;
- g_return_val_if_fail (request != NULL, -2);
- g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2);
- params = request->protocol_data;
- if (params->message.buffer != NULL)
- {
- sshv2_message_free (¶ms->message);
- params->count = 0;
- }
- if (params->handle_len > 0)
- {
- len = htonl (params->id++);
- memcpy (params->handle, &len, 4);
- if (sshv2_send_command (request, SSH_FXP_CLOSE, params->handle,
- params->handle_len) < 0)
- return (-2);
- memset (&message, 0, sizeof (message));
- if (sshv2_read_response (request, &message, -1) != SSH_FXP_STATUS)
- {
- request->logging_function (gftp_logging_error, request->user_data,
- _("Received wrong response from server, disconnectingn"));
- sshv2_message_free (&message);
- gftp_disconnect (request);
- return (-2);
- }
- sshv2_message_free (&message);
- params->handle_len = 0;
- }
- if (params->read_buffer != NULL)
- {
- g_free (params->read_buffer);
- params->read_buffer = NULL;
- }
- return (0);
- }
- static int
- sshv2_list_files (gftp_request * request)
- {
- sshv2_params * params;
- sshv2_message message;
- char *tempstr;
- gint32 len;
- int ret;
- g_return_val_if_fail (request != NULL, -2);
- g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2);
- g_return_val_if_fail (request->sockfd > 0, -2);
- params = request->protocol_data;
- request->logging_function (gftp_logging_misc, request->user_data,
- _("Retrieving directory listing...n"));
- tempstr = g_malloc (strlen (request->directory) + 9);
- len = htonl (params->id++);
- memcpy (tempstr, &len, 4);
- len = htonl (strlen (request->directory));
- memcpy (tempstr + 4, &len, 4);
- strcpy (tempstr + 8, request->directory);
- if (sshv2_send_command (request, SSH_FXP_OPENDIR, tempstr,
- strlen (request->directory) + 8) < 0)
- {
- g_free (tempstr);
- return (-2);
- }
- g_free (tempstr);
- memset (&message, 0, sizeof (message));
- ret = sshv2_read_response (request, &message, -1);
- if (ret == SSH_FXP_STATUS)
- {
- sshv2_message_free (&message);
- return (-2);
- }
- else if (ret != SSH_FXP_HANDLE)
- {
- request->logging_function (gftp_logging_error, request->user_data,
- _("Received wrong response from server, disconnectingn"));
- sshv2_message_free (&message);
- gftp_disconnect (request);
- return (-2);
- }
- if (message.length - 4 > SSH_MAX_HANDLE_SIZE)
- {
- request->logging_function (gftp_logging_error, request->user_data,
- _("Error: Message size %d too big from servern"),
- message.length - 4);
- sshv2_message_free (&message);
- gftp_disconnect (request);
- return (-1);
- }
- memset (params->handle, 0, 4);
- memcpy (params->handle + 4, message.buffer + 4, message.length - 5);
- params->handle_len = message.length - 1;
- sshv2_message_free (&message);
- params->count = 0;
- return (0);
- }
- static int
- sshv2_get_next_file (gftp_request * request, gftp_file * fle, int fd)
- {
- gint32 len, attrs, longnamelen;
- int ret, i, count, retsize;
- sshv2_params *params;
- char *longname;
- g_return_val_if_fail (request != NULL, -2);
- g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2);
- g_return_val_if_fail (fle != NULL, -2);
- params = request->protocol_data;
- if (request->last_dir_entry)
- {
- g_free (request->last_dir_entry);
- request->last_dir_entry = NULL;
- request->last_dir_entry_len = 0;
- }
- retsize = 0;
- if (params->count > 0)
- ret = SSH_FXP_NAME;
- else
- {
- if (!request->cached)
- {
- if (params->message.buffer != NULL)
- sshv2_message_free (¶ms->message);
- len = htonl (params->id++);
- memcpy (params->handle, &len, 4);
- if (sshv2_send_command (request, SSH_FXP_READDIR, params->handle,
- params->handle_len) < 0)
- return (-2);
- }
- if ((ret = sshv2_read_response (request, ¶ms->message, fd)) < 0)
- return (-2);
- if (!request->cached)
- {
- request->last_dir_entry = g_malloc (params->message.length + 4);
- len = htonl (params->message.length);
- memcpy (request->last_dir_entry, &len, 4);
- request->last_dir_entry[4] = params->message.command;
- memcpy (request->last_dir_entry + 5, params->message.buffer,
- params->message.length - 1);
- request->last_dir_entry_len = params->message.length + 4;
- }
- if (ret == SSH_FXP_NAME)
- {
- params->message.pos = params->message.buffer + 4;
- if ((params->count = sshv2_buffer_get_int32 (request,
- ¶ms->message, -1)) < 0)
- return (-2);
- }
- }
- if (ret == SSH_FXP_NAME)
- {
- if ((len = sshv2_buffer_get_int32 (request, ¶ms->message, -1)) < 0 ||
- params->message.pos + len > params->message.end)
- return (-2);
- params->message.pos += len;
- if ((longnamelen = sshv2_buffer_get_int32 (request,
- ¶ms->message, -1)) < 0 ||
- params->message.pos + longnamelen > params->message.end)
- return (-2);
- longname = params->message.pos;
- params->message.pos += longnamelen;
- if ((attrs = sshv2_buffer_get_int32 (request, ¶ms->message, -1)) < 0)
- return (-2);
- if (attrs & SSH_FILEXFER_ATTR_SIZE)
- {
- params->message.pos += 8;
- if (params->message.pos > params->message.end)
- {
- request->logging_function (gftp_logging_error, request->user_data,
- _("Received wrong response from server, disconnectingn"));
- sshv2_message_free (¶ms->message);
- gftp_disconnect (request);
- return (-2);
- }
- }
- if (attrs & SSH_FILEXFER_ATTR_UIDGID)
- {
- params->message.pos += 8;
- if (params->message.pos > params->message.end)
- {
- request->logging_function (gftp_logging_error, request->user_data,
- _("Received wrong response from server, disconnectingn"));
- sshv2_message_free (¶ms->message);
- gftp_disconnect (request);
- return (-2);
- }
- }
- if (attrs & SSH_FILEXFER_ATTR_PERMISSIONS)
- {
- params->message.pos += 4;
- if (params->message.pos > params->message.end)
- {
- request->logging_function (gftp_logging_error, request->user_data,
- _("Received wrong response from server, disconnectingn"));
- sshv2_message_free (¶ms->message);
- gftp_disconnect (request);
- return (-2);
- }
- }
- if (attrs & SSH_FILEXFER_ATTR_ACMODTIME)
- {
- params->message.pos += 8;
- if (params->message.pos > params->message.end)
- {
- request->logging_function (gftp_logging_error, request->user_data,
- _("Received wrong response from server, disconnectingn"));
- sshv2_message_free (¶ms->message);
- gftp_disconnect (request);
- return (-2);
- }
- }
- if (attrs & SSH_FILEXFER_ATTR_EXTENDED)
- {
- if ((count = sshv2_buffer_get_int32 (request,
- ¶ms->message, -1)) < 0)
- return (-2);
- for (i=0; i<count; i++)
- {
- if ((len = sshv2_buffer_get_int32 (request,
- ¶ms->message, -1)) < 0 ||
- params->message.pos + len + 4 > params->message.end)
- return (-2);
- params->message.pos += len + 4;
- if ((len = sshv2_buffer_get_int32 (request,
- ¶ms->message, -1)) < 0 ||
- params->message.pos + len + 4 > params->message.end)
- return (-2);
- params->message.pos += len + 4;
- }
- }
- longname[longnamelen] = ' ';
- /* The commercial SSH2 puts a / and * after some entries */
- if (longname[longnamelen - 1] == '*')
- longname[--longnamelen] = ' ';
- if (longname[longnamelen - 1] == '/')
- longname[--longnamelen] = ' ';
- if (gftp_parse_ls (longname, fle) != 0)
- {
- gftp_file_destroy (fle);
- return (-2);
- }
- retsize = strlen (longname);
- params->count--;
- }
- else if (ret == SSH_FXP_STATUS)
- {
- sshv2_message_free (¶ms->message);
- return (0);
- }
- else
- {
- request->logging_function (gftp_logging_error, request->user_data,
- _("Received wrong response from server, disconnectingn"));
- sshv2_message_free (¶ms->message);
- gftp_disconnect (request);
- return (-2);
- }
- return (retsize);
- }
- static int
- sshv2_chdir (gftp_request * request, const char *directory)
- {
- sshv2_message message;
- sshv2_params * params;
- char *tempstr, *dir;
- gint32 num;
- size_t len;
- int ret;
- g_return_val_if_fail (request != NULL, -2);
- g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2);
- params = request->protocol_data;
- if (request->directory != directory)
- {
- if (*directory == '/')
- {
- len = strlen (directory) + 8;
- tempstr = g_malloc (len + 1);
- strcpy (tempstr + 8, directory);
- }
- else
- {
- len = strlen (directory) + strlen (request->directory) + 9;
- tempstr = g_malloc (len + 1);
- strcpy (tempstr + 8, request->directory);
- strcat (tempstr + 8, "/");
- strcat (tempstr + 8, directory);
- }
- num = htonl (params->id++);
- memcpy (tempstr, &num, 4);
- num = htonl (len - 8);
- memcpy (tempstr + 4, &num, 4);
- if (sshv2_send_command (request, SSH_FXP_REALPATH, tempstr, len) < 0)
- {
- g_free (tempstr);
- return (-2);
- }
- g_free (tempstr);
- memset (&message, 0, sizeof (message));
- ret = sshv2_read_response (request, &message, -1);
- if (ret == SSH_FXP_STATUS)
- {
- sshv2_message_free (&message);
- return (-2);
- }
- else if (ret != SSH_FXP_NAME)
- {
- request->logging_function (gftp_logging_error, request->user_data,
- _("Received wrong response from server, disconnectingn"));
- sshv2_message_free (&message);
- gftp_disconnect (request);
- return (-2);
- }
- message.pos += 4;
- if (sshv2_buffer_get_int32 (request, &message, 1) != 1)
- return (-2);
- if ((dir = sshv2_buffer_get_string (request, &message)) == NULL)
- return (-2);
- if (request->directory)
- g_free (request->directory);
- request->directory = dir;
- sshv2_message_free (&message);
- return (0);
- }
- else
- return (sshv2_getcwd (request));
- }
- static int
- sshv2_rmdir (gftp_request * request, const char *directory)
- {
- sshv2_params * params;
- sshv2_message message;
- char *tempstr;
- gint32 num;
- size_t len;
- g_return_val_if_fail (request != NULL, -2);
- g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2);
- g_return_val_if_fail (directory != NULL, -2);
- params = request->protocol_data;
- if (*directory == '/')
- {
- len = strlen (directory) + 8;
- tempstr = g_malloc (len + 1);
- strcpy (tempstr + 8, directory);
- }
- else
- {
- len = strlen (directory) + strlen (request->directory) + 9;
- tempstr = g_malloc (len + 1);
- strcpy (tempstr + 8, request->directory);
- strcat (tempstr + 8, "/");
- strcat (tempstr + 8, directory);
- }
- num = htonl (params->id++);
- memcpy (tempstr, &num, 4);
- num = htonl (len - 8);
- memcpy (tempstr + 4, &num, 4);
- if (sshv2_send_command (request, SSH_FXP_RMDIR, tempstr, len) < 0)
- {
- g_free (tempstr);
- return (-2);
- }
- g_free (tempstr);
- memset (&message, 0, sizeof (message));
- if (sshv2_read_response (request, &message, -1) < 0)
- return (-2);
- message.pos += 4;
- if (sshv2_buffer_get_int32 (request, &message, SSH_FX_OK) < 0)
- return (-2);
- sshv2_message_free (&message);
- return (0);
- }
- static int
- sshv2_rmfile (gftp_request * request, const char *file)
- {
- sshv2_params * params;
- sshv2_message message;
- char *tempstr;
- gint32 num;
- size_t len;
- g_return_val_if_fail (request != NULL, -2);
- g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2);
- g_return_val_if_fail (file != NULL, -2);
- params = request->protocol_data;
- if (*file == '/')
- {
- len = strlen (file) + 8;
- tempstr = g_malloc (len + 1);
- strcpy (tempstr + 8, file);
- }
- else
- {
- len = strlen (file) + strlen (request->directory) + 9;
- tempstr = g_malloc (len + 1);
- strcpy (tempstr + 8, request->directory);
- strcat (tempstr + 8, "/");
- strcat (tempstr + 8, file);
- }
- num = htonl (params->id++);
- memcpy (tempstr, &num, 4);
- num = htonl (len - 8);
- memcpy (tempstr + 4, &num, 4);
- if (sshv2_send_command (request, SSH_FXP_REMOVE, tempstr, len) < 0)
- {
- g_free (tempstr);
- return (-2);
- }
- g_free (tempstr);
- memset (&message, 0, sizeof (message));
- if (sshv2_read_response (request, &message, -1) < 0)
- return (-2);
- message.pos += 4;
- if (sshv2_buffer_get_int32 (request, &message, SSH_FX_OK) < 0)
- return (-2);
- sshv2_message_free (&message);
- return (0);
- }
- static int
- sshv2_chmod (gftp_request * request, const char *file, int mode)
- {
- char *tempstr, buf[10];
- sshv2_params * params;
- sshv2_message message;
- gint32 num;
- size_t len;
- g_return_val_if_fail (request != NULL, -2);
- g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2);
- g_return_val_if_fail (file != NULL, -2);
- params = request->protocol_data;
- if (*file == '/')
- {
- len = strlen (file) + 16;
- tempstr = g_malloc (len + 1);
- strcpy (tempstr + 8, file);
- }
- else
- {
- len = strlen (file) + strlen (request->directory) + 17;
- tempstr = g_malloc (len + 1);
- strcpy (tempstr + 8, request->directory);
- strcat (tempstr + 8, "/");
- strcat (tempstr + 8, file);
- }
- num = htonl (params->id++);
- memcpy (tempstr, &num, 4);
- num = htonl (len - 16);
- memcpy (tempstr + 4, &num, 4);
- num = htonl (SSH_FILEXFER_ATTR_PERMISSIONS);
- memcpy (tempstr + len - 8, &num, 4);
- g_snprintf (buf, sizeof (buf), "%d", mode);
- num = htonl (strtol (buf, NULL, 8));
- memcpy (tempstr + len - 4, &num, 4);
- if (sshv2_send_command (request, SSH_FXP_SETSTAT, tempstr, len) < 0)
- {
- g_free (tempstr);
- return (-2);
- }
- g_free (tempstr);
- memset (&message, 0, sizeof (message));
- if (sshv2_read_response (request, &message, -1) < 0)
- return (-2);
- message.pos += 4;
- if (sshv2_buffer_get_int32 (request, &message, SSH_FX_OK) < 0)
- return (-2);
- sshv2_message_free (&message);
- return (0);
- }
- static int
- sshv2_mkdir (gftp_request * request, const char *newdir)
- {
- sshv2_params * params;
- sshv2_message message;
- char *tempstr;
- gint32 num;
- size_t len;
- g_return_val_if_fail (request != NULL, -2);
- g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2);
- g_return_val_if_fail (newdir != NULL, -2);
- params = request->protocol_data;
- if (*newdir == '/')
- {
- len = strlen (newdir) + 12;
- tempstr = g_malloc (len + 1);
- strcpy (tempstr + 8, newdir);
- }
- else
- {
- len = strlen (newdir) + strlen (request->directory) + 13;
- tempstr = g_malloc (len + 1);
- strcpy (tempstr + 8, request->directory);
- strcat (tempstr + 8, "/");
- strcat (tempstr + 8, newdir);
- }
- num = htonl (params->id++);
- memcpy (tempstr, &num, 4);
- num = htonl (len - 12);
- memcpy (tempstr + 4, &num, 4);
- memset (tempstr + len - 4, 0, 4); /* attributes */
- if (sshv2_send_command (request, SSH_FXP_MKDIR, tempstr, len) < 0)
- {
- g_free (tempstr);
- return (-2);
- }
- g_free (tempstr);
- memset (&message, 0, sizeof (message));
- if (sshv2_read_response (request, &message, -1) < 0)
- return (-2);
- message.pos += 4;
- if (sshv2_buffer_get_int32 (request, &message, SSH_FX_OK) < 0)
- return (-2);
- sshv2_message_free (&message);
- return (0);
- }
- static int
- sshv2_rename (gftp_request * request, const char *oldname, const char *newname)
- {
- char *tempstr, *oldstr, *newstr;
- sshv2_params * params;
- sshv2_message message;
- gint32 num;
- size_t oldlen, newlen;
- g_return_val_if_fail (request != NULL, -2);
- g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2);
- g_return_val_if_fail (oldname != NULL, -2);
- g_return_val_if_fail (newname != NULL, -2);
- params = request->protocol_data;
- if (*oldname == '/')
- {
- oldlen = strlen (oldname);
- oldstr = g_strdup (oldname);
- }
- else
- {
- oldlen = strlen (request->directory) + strlen (oldname) + 1;
- oldstr = g_strconcat (request->directory, "/", oldname, NULL);
- }
- if (*newname == '/')
- {
- newlen = strlen (newname);
- newstr = g_strdup (newname);
- }
- else
- {
- newlen = strlen (request->directory) + strlen (newname) + 1;
- newstr = g_strconcat (request->directory, "/", newname, NULL);
- }
- tempstr = g_malloc (oldlen + newlen + 13);
- num = htonl (params->id++);
- memcpy (tempstr, &num, 4);
- num = htonl (oldlen);
- memcpy (tempstr + 4, &num, 4);
- strcpy (tempstr + 8, oldstr);
- num = htonl (newlen);
- memcpy (tempstr + 8 + oldlen, &num, 4);
- strcpy (tempstr + 12 + oldlen, newstr);
- if (sshv2_send_command (request, SSH_FXP_RENAME, tempstr, oldlen + newlen + 12) < 0)
- {
- g_free (tempstr);
- return (-2);
- }
- g_free (tempstr);
- memset (&message, 0, sizeof (message));
- if (sshv2_read_response (request, &message, -1) < 0)
- return (-2);
- message.pos += 4;
- if (sshv2_buffer_get_int32 (request, &message, SSH_FX_OK) < 0)
- return (-2);
- sshv2_message_free (&message);
- return (0);
- }
- static int
- sshv2_set_file_time (gftp_request * request, const char *file, time_t datetime)
- {
- sshv2_params * params;
- sshv2_message message;
- char *tempstr;
- gint32 num;
- size_t len;
- g_return_val_if_fail (request != NULL, -2);
- g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2);
- g_return_val_if_fail (file != NULL, -2);
- params = request->protocol_data;
- if (*file == '/')
- {
- len = strlen (file) + 20;
- tempstr = g_malloc (len + 1);
- strcpy (tempstr + 8, file);
- }
- else
- {
- len = strlen (file) + strlen (request->directory) + 21;
- tempstr = g_malloc (len + 1);
- strcpy (tempstr + 8, request->directory);
- strcat (tempstr + 8, "/");
- strcat (tempstr + 8, file);
- }
- num = htonl (params->id++);
- memcpy (tempstr, &num, 4);
- num = htonl (len - 20);
- memcpy (tempstr + 4, &num, 4);
- num = htonl (SSH_FILEXFER_ATTR_ACMODTIME);
- memcpy (tempstr + len - 12, &num, 4);
- num = htonl (datetime);
- memcpy (tempstr + len - 8, &num, 4);
- num = htonl (datetime);
- memcpy (tempstr + len - 4, &num, 4);
- if (sshv2_send_command (request, SSH_FXP_SETSTAT, tempstr, len) < 0)
- {
- g_free (tempstr);
- return (-2);
- }
- g_free (tempstr);
- memset (&message, 0, sizeof (message));
- if (sshv2_read_response (request, &message, -1) < 0)
- return (-2);
- message.pos += 4;
- if (sshv2_buffer_get_int32 (request, &message, SSH_FX_OK) < 0)
- return (-2);
- sshv2_message_free (&message);
- return (0);
- }
- static off_t
- sshv2_get_file_size (gftp_request * request, const char *file)
- {
- gint32 len, highnum, lownum, attrs, num;
- sshv2_params * params;
- char *tempstr;
- int serv_ret;
- #ifdef G_HAVE_GINT64
- gint64 ret;
- #endif
- g_return_val_if_fail (request != NULL, -2);
- g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2);
- g_return_val_if_fail (file != NULL, -2);
- params = request->protocol_data;
- if (*file == '/')
- {
- len = strlen (file);
- tempstr = g_malloc (len + 9);
- strcpy (tempstr + 8, file);
- }
- else
- {
- len = strlen (file) + strlen (request->directory) + 1;
- tempstr = g_malloc (len + 9);
- strcpy (tempstr + 8, request->directory);
- strcat (tempstr + 8, "/");
- strcat (tempstr + 8, file);
- }
- num = htonl (params->id++);
- memcpy (tempstr, &num, 4);
- num = htonl (len);
- memcpy (tempstr + 4, &num, 4);
- if (sshv2_send_command (request, SSH_FXP_STAT, tempstr, len + 8) < 0)
- {
- g_free (tempstr);
- return (-2);
- }
- g_free (tempstr);
- memset (¶ms->message, 0, sizeof (params->message));
- serv_ret = sshv2_read_response (request, ¶ms->message, -1);
- if (serv_ret == SSH_FXP_STATUS)
- {
- sshv2_message_free (¶ms->message);
- return (-2);
- }
- else if (serv_ret != SSH_FXP_ATTRS)
- {
- request->logging_function (gftp_logging_error, request->user_data,
- _("Received wrong response from server, disconnectingn"));
- sshv2_message_free (¶ms->message);
- gftp_disconnect (request);
- return (-2);
- }
- if (params->message.length < 5)
- return (-2);
- params->message.pos += 4;
- if ((attrs = sshv2_buffer_get_int32 (request, ¶ms->message, -1)) < 0)
- return (-2);
- if (attrs & SSH_FILEXFER_ATTR_SIZE)
- {
- if ((highnum = sshv2_buffer_get_int32 (request, ¶ms->message, -1)) < 0)
- return (-2);
- if ((lownum = sshv2_buffer_get_int32 (request, ¶ms->message, -1)) < 0)
- return (-2);
- sshv2_message_free (¶ms->message);
- #if G_HAVE_GINT64
- ret = (gint64) lownum | ((gint64) highnum >> 32);
- return (ret);
- #else
- return (lownum);
- #endif
- }
- sshv2_message_free (¶ms->message);
- return (0);
- }
- static off_t
- sshv2_get_file (gftp_request * request, const char *file, int fd,
- off_t startsize)
- {
- sshv2_params * params;
- sshv2_message message;
- char *tempstr;
- size_t stlen;
- gint32 num;
- int ret;
- g_return_val_if_fail (request != NULL, -2);
- g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2);
- g_return_val_if_fail (request->sockfd > 0, -2);
- /* fd ignored for this protocol */
- params = request->protocol_data;
- params->offset = startsize;
- if (*file == '/')
- {
- stlen = strlen (file);
- tempstr = g_malloc (stlen + 16);
- strcpy (tempstr + 8, file);
- }
- else
- {
- stlen = strlen (file) + strlen (request->directory) + 1;
- tempstr = g_malloc (stlen + 16);
- strcpy (tempstr + 8, request->directory);
- strcat (tempstr + 8, "/");
- strcat (tempstr + 8, file);
- }
- num = htonl (params->id++);
- memcpy (tempstr, &num, 4);
- num = htonl (stlen);
- memcpy (tempstr + 4, &num, 4);
- num = htonl (SSH_FXF_READ);
- memcpy (tempstr + 8 + stlen, &num, 4);
- memset (tempstr + 12 + stlen, 0, 4);
- if (sshv2_send_command (request, SSH_FXP_OPEN, tempstr, stlen + 16) < 0)
- {
- g_free (tempstr);
- return (-2);
- }
- g_free (tempstr);
- memset (&message, 0, sizeof (message));
- ret = sshv2_read_response (request, &message, -1);
- if (ret == SSH_FXP_STATUS)
- {
- sshv2_message_free (&message);
- return (-2);
- }
- else if (ret != SSH_FXP_HANDLE)
- {
- request->logging_function (gftp_logging_error, request->user_data,
- _("Received wrong response from server, disconnectingn"));
- sshv2_message_free (&message);
- gftp_disconnect (request);
- return (-2);
- }
- if (message.length - 4 > SSH_MAX_HANDLE_SIZE)
- {
- request->logging_function (gftp_logging_error, request->user_data,
- _("Error: Message size %d too big from servern"),
- message.length - 4);
- sshv2_message_free (&message);
- gftp_disconnect (request);
- return (-1);
- }
- memset (params->handle, 0, 4);
- memcpy (params->handle + 4, message.buffer+ 4, message.length - 5);
- params->handle_len = message.length - 1;
- sshv2_message_free (&message);
- return (sshv2_get_file_size (request, file));
- }
- static int
- sshv2_put_file (gftp_request * request, const char *file, int fd,
- off_t startsize, off_t totalsize)
- {
- sshv2_params * params;
- sshv2_message message;
- char *tempstr;
- size_t stlen;
- gint32 num;
- int ret;
- g_return_val_if_fail (request != NULL, -2);
- g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2);
- g_return_val_if_fail (request->sockfd > 0, -2);
- /* fd ignored for this protocol */
- params = request->protocol_data;
- params->offset = 0;
- if (*file == '/')
- {
- stlen = strlen (file);
- tempstr = g_malloc (stlen + 16);
- strcpy (tempstr + 8, file);
- }
- else
- {
- stlen = strlen (file) + strlen (request->directory) + 1;
- tempstr = g_malloc (stlen + 16);
- strcpy (tempstr + 8, request->directory);
- strcat (tempstr + 8, "/");
- strcat (tempstr + 8, file);
- }
- num = htonl (params->id++);
- memcpy (tempstr, &num, 4);
- num = htonl (stlen);
- memcpy (tempstr + 4, &num, 4);
- if (startsize > 0)
- num = htonl (SSH_FXF_WRITE | SSH_FXF_CREAT | SSH_FXF_APPEND);
- else
- num = htonl (SSH_FXF_WRITE | SSH_FXF_CREAT | SSH_FXF_TRUNC);
- memcpy (tempstr + 8 + stlen, &num, 4);
- memset (tempstr + 12 + stlen, 0, 4);
- if (sshv2_send_command (request, SSH_FXP_OPEN, tempstr, stlen + 16) < 0)
- {
- g_free (tempstr);
- return (-2);
- }
- g_free (tempstr);
- memset (&message, 0, sizeof (message));
- ret = sshv2_read_response (request, &message, -1);
- if (ret == SSH_FXP_STATUS)
- {
- sshv2_message_free (&message);
- return (-2);
- }
- else if (ret != SSH_FXP_HANDLE)
- {
- request->logging_function (gftp_logging_error, request->user_data,
- _("Received wrong response from server, disconnectingn"));
- sshv2_message_free (&message);
- gftp_disconnect (request);
- return (-2);
- }
- if (message.length - 4 > SSH_MAX_HANDLE_SIZE)
- {
- request->logging_function (gftp_logging_error, request->user_data,
- _("Error: Message size %d too big from servern"),
- message.length - 4);
- sshv2_message_free (&message);
- gftp_disconnect (request);
- return (-1);
- }
- memset (params->handle, 0, 4);
- memcpy (params->handle + 4, message.buffer+ 4, message.length - 5);
- params->handle_len = message.length - 1;
- sshv2_message_free (&message);
- return (0);
- }
- static ssize_t
- sshv2_get_next_file_chunk (gftp_request * request, char *buf, size_t size)
- {
- sshv2_params * params;
- sshv2_message message;
- gint32 num;
- #ifdef G_HAVE_GINT64
- gint64 offset;
- #else
- gint32 offset;
- #endif
- g_return_val_if_fail (request != NULL, -2);
- g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2);
- g_return_val_if_fail (request->sockfd > 0, -2);
- g_return_val_if_fail (buf != NULL, -2);
- params = request->protocol_data;
- if (params->read_buffer == NULL)
- {
- params->read_buffer = g_malloc (params->handle_len + 12);
- num = htonl (params->handle_len);
- memcpy (params->read_buffer, params->handle, params->handle_len);
- }
- num = htonl (params->id++);
- memcpy (params->read_buffer, &num, 4);
- #ifdef G_HAVE_GINT64
- offset = hton64 (params->offset);
- memcpy (params->read_buffer + params->handle_len, &offset, 8);
- #else
- memset (params->read_buffer + params->handle_len, 0, 4);
- offset = htonl (params->offset);
- memcpy (params->read_buffer + params->handle_len + 4, &offset, 4);
- #endif
- num = htonl (size);
- memcpy (params->read_buffer + params->handle_len + 8, &num, 4);
- if (sshv2_send_command (request, SSH_FXP_READ, params->read_buffer, params->handle_len + 12) < 0)
- return (-2);
- memset (&message, 0, sizeof (message));
- if (sshv2_read_response (request, &message, -1) != SSH_FXP_DATA)
- {
- message.pos += 4;
- if ((num = sshv2_buffer_get_int32 (request, &message, SSH_FX_OK)) < 0)
- return (-2);
- sshv2_message_free (&message);
- if (num != SSH_FX_EOF)
- {
- request->logging_function (gftp_logging_error, request->user_data,
- _("Received wrong response from server, disconnectingn"));
- gftp_disconnect (request);
- return (-2);
- }
- return (0);
- }
- memcpy (&num, message.buffer + 4, 4);
- num = ntohl (num);
- if (num > size)
- {
- request->logging_function (gftp_logging_error, request->user_data,
- _("Error: Message size %d too big from servern"),
- num);
- sshv2_message_free (&message);
- gftp_disconnect (request);
- return (-1);
- }
- memcpy (buf, message.buffer + 8, num);
- sshv2_message_free (&message);
- params->offset += num;
- return (num);
- }
- static ssize_t
- sshv2_put_next_file_chunk (gftp_request * request, char *buf, size_t size)
- {
- sshv2_params * params;
- sshv2_message message;
- char tempstr[32768];
- gint32 num;
- int ret;
- #ifdef G_HAVE_GINT64
- gint64 offset;
- #else
- gint32 offset;
- #endif
- g_return_val_if_fail (request != NULL, -2);
- g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2);
- g_return_val_if_fail (request->sockfd > 0, -2);
- g_return_val_if_fail (buf != NULL, -2);
- g_return_val_if_fail (size <= 32500, -2);
- params = request->protocol_data;
- num = htonl (params->handle_len);
- memcpy (tempstr, params->handle, params->handle_len);
- num = htonl (params->id++);
- memcpy (tempstr, &num, 4);
- #ifdef G_HAVE_GINT64
- offset = hton64 (params->offset);
- memcpy (tempstr + params->handle_len, &offset, 8);
- #else
- memset (tempstr + params->handle_len, 0, 4);
- offset = htonl (params->offset);
- memcpy (tempstr + params->handle_len + 4, &offset, 4);
- #endif
- num = htonl (size);
- memcpy (tempstr + params->handle_len + 8, &num, 4);
- memcpy (tempstr + params->handle_len + 12, buf, size);
- if (sshv2_send_command (request, SSH_FXP_WRITE, tempstr, params->handle_len + size + 12) < 0)
- {
- g_free (tempstr);
- return (-2);
- }
- memset (&message, 0, sizeof (message));
- params->dont_log_status = 1;
- ret = sshv2_read_response (request, &message, -1);
- params->dont_log_status = 0;
- if (ret != SSH_FXP_STATUS)
- {
- request->logging_function (gftp_logging_error, request->user_data,
- _("Received wrong response from server, disconnectingn"));
- sshv2_message_free (&message);
- gftp_disconnect (request);
- return (-2);
- }
- message.pos += 4;
- if ((num = sshv2_buffer_get_int32 (request, &message, SSH_FX_OK)) < 0)
- return (-2);
- sshv2_message_free (&message);
- if (num == SSH_FX_EOF)
- return (0);
- else if (num != SSH_FX_OK)
- return (-1);
- params->offset += size;
- return (size);
- }
- static void
- sshv2_set_config_options (gftp_request * request)
- {
- if (request->sftpserv_path != NULL)
- {
- if (ssh2_sftp_path != NULL &&
- strcmp (ssh2_sftp_path, request->sftpserv_path) == 0)
- return;
- g_free (request->sftpserv_path);
- request->sftpserv_path = NULL;
- }
- if (ssh2_sftp_path != NULL)
- request->sftpserv_path = g_strdup (ssh2_sftp_path);
- request->need_userpass = ssh_need_userpass;
- }
- static void
- sshv2_swap_socks (gftp_request * dest, gftp_request * source)
- {
- sshv2_params * sparams, * dparams;
- sparams = source->protocol_data;
- dparams = dest->protocol_data;
- dparams->id = sparams->id;
- }
- void
- sshv2_init (gftp_request * request)
- {
- sshv2_params * params;
- g_return_if_fail (request != NULL);
- request->protonum = GFTP_SSHV2_NUM;
- request->init = sshv2_init;
- request->destroy = sshv2_destroy;
- request->connect = sshv2_connect;
- request->disconnect = sshv2_disconnect;
- request->get_file = sshv2_get_file;
- request->put_file = sshv2_put_file;
- request->transfer_file = NULL;
- request->get_next_file_chunk = sshv2_get_next_file_chunk;
- request->put_next_file_chunk = sshv2_put_next_file_chunk;
- request->end_transfer = sshv2_end_transfer;
- request->abort_transfer = sshv2_end_transfer; /* NOTE: uses sshv2_end_transfer */
- request->list_files = sshv2_list_files;
- request->get_next_file = sshv2_get_next_file;
- request->set_data_type = NULL;
- request->get_file_size = sshv2_get_file_size;
- request->chdir = sshv2_chdir;
- request->rmdir = sshv2_rmdir;
- request->rmfile = sshv2_rmfile;
- request->mkdir = sshv2_mkdir;
- request->rename = sshv2_rename;
- request->chmod = sshv2_chmod;
- request->set_file_time = sshv2_set_file_time;
- request->site = NULL;
- request->parse_url = NULL;
- request->set_config_options = sshv2_set_config_options;
- request->swap_socks = sshv2_swap_socks;
- request->url_prefix = "ssh2";
- request->protocol_name = "SSH2";
- request->need_hostport = 1;
- request->need_userpass = ssh_need_userpass;
- request->use_cache = 1;
- request->use_threads = 1;
- request->always_connected = 0;
- request->protocol_data = g_malloc0 (sizeof (sshv2_params));
- gftp_set_config_options (request);
- params = request->protocol_data;
- params->id = 1;
- }