Mercurial > gftp.yaz
annotate lib/sshv2.c @ 56:a12bcbc2fce4
2002-11-11 Brian Masney <masneyb@gftp.org>
* src/gtk/dnd.c - fixes to DnD code
* src/gtk/gftp-gtk.[ch] - added main_thread_id variable
* src/gtk/misc-gtk.c (ftp_log) - don't check the user_data to see if
we're in a child thread, instead compare the value of pthread_self()
with main_thread_id
* src/gtk/chmod_dialog.c src/gtk/delete_dialog.c src/gtk/menu-items.c
src/gtk/mkdir_dialog.c src/gtk/rename_dialog.c src/gtk/transfer.c -
don't set user_data to 0x1 if we're in a child thread
* lib/gftp.h src/gtk/misc-gtk.c src/text/gftp-text.c - make
r_getservbyname() available even if HAVE_GERADDRINFO is defined
* lib/misc.c (make_ssh_exec_args) - if port is zero, lookup the default
port for the ssh service
* lib/protocols.c (gftp_connect_server) - if the port is zero, store
the default port for that protocol there
* src/gtk/transfer.c - added function update_window_transfer_bytes().
Be able to update the directory download progress in window1 now
* lib/config_file.c lib/misc.c lib/protocols.c lib/ssh.c lib/sshv2.c
src/text/gftp-text.c - use g_strdup() instead of g_strconcat() where
needed
author | masneyb |
---|---|
date | Mon, 11 Nov 2002 23:16:12 +0000 |
parents | e5f6054590b5 |
children | c01d91c10f6c |
rev | line source |
---|---|
1 | 1 /*****************************************************************************/ |
2 /* sshv2.c - functions that will use the sshv2 protocol */ | |
3 /* Copyright (C) 1998-2002 Brian Masney <masneyb@gftp.org> */ | |
4 /* */ | |
5 /* This program is free software; you can redistribute it and/or modify */ | |
6 /* it under the terms of the GNU General Public License as published by */ | |
7 /* the Free Software Foundation; either version 2 of the License, or */ | |
8 /* (at your option) any later version. */ | |
9 /* */ | |
10 /* This program is distributed in the hope that it will be useful, */ | |
11 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ | |
12 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ | |
13 /* GNU General Public License for more details. */ | |
14 /* */ | |
15 /* You should have received a copy of the GNU General Public License */ | |
16 /* along with this program; if not, write to the Free Software */ | |
17 /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA */ | |
18 /*****************************************************************************/ | |
19 | |
20 #include "gftp.h" | |
33 | 21 static const char cvsid[] = "$Id$"; |
1 | 22 |
23 #define SSH_MAX_HANDLE_SIZE 256 | |
24 #define SSH_MAX_STRING_SIZE 34000 | |
25 | |
26 typedef struct sshv2_attribs_tag | |
27 { | |
28 gint32 flags; | |
29 gint64 size; | |
30 gint32 uid; | |
31 gint32 gid; | |
32 gint32 perm; | |
33 gint32 atime; | |
34 gint32 mtime; | |
35 } sshv2_attribs; | |
36 | |
37 typedef struct sshv2_message_tag | |
38 { | |
39 gint32 length; | |
40 char command; | |
41 char *buffer, | |
42 *pos, | |
43 *end; | |
44 } sshv2_message; | |
45 | |
46 typedef struct sshv2_params_tag | |
47 { | |
48 char handle[SSH_MAX_HANDLE_SIZE + 4]; /* We'll encode the ID in here too */ | |
49 int handle_len, | |
50 dont_log_status : 1; /* For uploading files */ | |
51 sshv2_message message; | |
52 | |
53 gint32 id, | |
54 count; | |
55 #ifdef G_HAVE_GINT64 | |
56 gint64 offset; | |
57 #else | |
58 gint32 offset; | |
59 #endif | |
60 char *read_buffer; | |
61 } sshv2_params; | |
62 | |
63 | |
64 #define SSH_MY_VERSION 3 | |
65 | |
66 #define SSH_FXP_INIT 1 | |
67 #define SSH_FXP_VERSION 2 | |
68 #define SSH_FXP_OPEN 3 | |
69 #define SSH_FXP_CLOSE 4 | |
70 #define SSH_FXP_READ 5 | |
71 #define SSH_FXP_WRITE 6 | |
72 #define SSH_FXP_LSTAT 7 | |
73 #define SSH_FXP_FSTAT 8 | |
74 #define SSH_FXP_SETSTAT 9 | |
75 #define SSH_FXP_FSETSTAT 10 | |
76 #define SSH_FXP_OPENDIR 11 | |
77 #define SSH_FXP_READDIR 12 | |
78 #define SSH_FXP_REMOVE 13 | |
79 #define SSH_FXP_MKDIR 14 | |
80 #define SSH_FXP_RMDIR 15 | |
81 #define SSH_FXP_REALPATH 16 | |
82 #define SSH_FXP_STAT 17 | |
83 #define SSH_FXP_RENAME 18 | |
84 #define SSH_FXP_STATUS 101 | |
85 #define SSH_FXP_HANDLE 102 | |
86 #define SSH_FXP_DATA 103 | |
87 #define SSH_FXP_NAME 104 | |
88 #define SSH_FXP_ATTRS 105 | |
89 #define SSH_FXP_EXTENDED 200 | |
90 #define SSH_FXP_EXTENDED_REPLY 201 | |
91 | |
92 #define SSH_FILEXFER_ATTR_SIZE 0x00000001 | |
93 #define SSH_FILEXFER_ATTR_UIDGID 0x00000002 | |
94 #define SSH_FILEXFER_ATTR_PERMISSIONS 0x00000004 | |
95 #define SSH_FILEXFER_ATTR_ACMODTIME 0x00000008 | |
96 #define SSH_FILEXFER_ATTR_EXTENDED 0x80000000 | |
97 | |
98 #define SSH_FXF_READ 0x00000001 | |
99 #define SSH_FXF_WRITE 0x00000002 | |
100 #define SSH_FXF_APPEND 0x00000004 | |
101 #define SSH_FXF_CREAT 0x00000008 | |
102 #define SSH_FXF_TRUNC 0x00000010 | |
103 #define SSH_FXF_EXCL 0x00000020 | |
104 | |
105 #define SSH_FX_OK 0 | |
106 #define SSH_FX_EOF 1 | |
107 #define SSH_FX_NO_SUCH_FILE 2 | |
108 #define SSH_FX_PERMISSION_DENIED 3 | |
109 #define SSH_FX_FAILURE 4 | |
110 #define SSH_FX_BAD_MESSAGE 5 | |
111 #define SSH_FX_NO_CONNECTION 6 | |
112 #define SSH_FX_CONNECTION_LOST 7 | |
113 #define SSH_FX_OP_UNSUPPORTED 8 | |
114 | |
115 | |
48 | 116 static void |
117 sshv2_log_command (gftp_request * request, gftp_logging_level level, | |
118 char type, char *message, size_t length) | |
1 | 119 { |
48 | 120 gint32 id, num, attr, stattype; |
121 char *descr, *pos, oldchar; | |
1 | 122 sshv2_params * params; |
123 | |
48 | 124 params = request->protocol_data; |
125 memcpy (&id, message, 4); | |
126 id = ntohl (id); | |
127 switch (type) | |
128 { | |
129 case SSH_FXP_INIT: | |
130 request->logging_function (level, request->user_data, | |
131 _("%d: Protocol Initialization\n"), id); | |
132 break; | |
133 case SSH_FXP_VERSION: | |
134 memcpy (&num, message, 4); | |
135 num = ntohl (num); | |
136 request->logging_function (level, request->user_data, | |
137 _("%d: Protocol version %d\n"), id, num); | |
138 break; | |
139 case SSH_FXP_OPEN: | |
140 memcpy (&num, message + 4, 4); | |
141 num = ntohl (num); | |
142 pos = message + 12 + num - 1; | |
143 oldchar = *pos; | |
144 *pos = '\0'; | |
145 request->logging_function (level, request->user_data, | |
146 _("%d: Open %s\n"), id, message + 8); | |
147 *pos = oldchar; | |
148 break; | |
149 case SSH_FXP_CLOSE: | |
150 request->logging_function (level, request->user_data, | |
151 _("%d: Close\n"), id); | |
152 case SSH_FXP_READ: | |
153 case SSH_FXP_WRITE: | |
154 break; | |
155 case SSH_FXP_OPENDIR: | |
156 request->logging_function (level, request->user_data, | |
157 _("%d: Open Directory %s\n"), id, | |
158 message + 8); | |
159 break; | |
160 case SSH_FXP_READDIR: | |
161 request->logging_function (level, request->user_data, | |
162 _("%d: Read Directory\n"), id); | |
163 break; | |
164 case SSH_FXP_REMOVE: | |
165 request->logging_function (level, request->user_data, | |
166 _("%d: Remove file %s\n"), id, | |
167 message + 8); | |
168 break; | |
169 case SSH_FXP_MKDIR: | |
170 request->logging_function (level, request->user_data, | |
171 _("%d: Make directory %s\n"), id, | |
172 message + 8); | |
173 break; | |
174 case SSH_FXP_RMDIR: | |
175 request->logging_function (level, request->user_data, | |
176 _("%d: Remove directory %s\n"), id, | |
177 message + 8); | |
178 break; | |
179 case SSH_FXP_REALPATH: | |
180 request->logging_function (level, request->user_data, | |
181 _("%d: Realpath %s\n"), id, | |
182 message + 8); | |
183 break; | |
184 case SSH_FXP_ATTRS: | |
185 request->logging_function (level, request->user_data, | |
186 _("%d: File attributes\n"), id); | |
187 break; | |
188 case SSH_FXP_STAT: | |
189 request->logging_function (level, request->user_data, | |
190 _("%d: Stat %s\n"), id, | |
191 message + 8); | |
192 break; | |
193 case SSH_FXP_SETSTAT: | |
194 memcpy (&num, message + 4, 4); | |
195 num = ntohl (num); | |
196 pos = message + 12 + num - 1; | |
197 oldchar = *pos; | |
198 *pos = '\0'; | |
199 memcpy (&stattype, message + 8 + num, 4); | |
200 stattype = ntohl (stattype); | |
201 memcpy (&attr, message + 12 + num, 4); | |
202 attr = ntohl (attr); | |
203 switch (stattype) | |
204 { | |
205 case SSH_FILEXFER_ATTR_PERMISSIONS: | |
206 request->logging_function (level, request->user_data, | |
207 _("%d: Chmod %s %o\n"), id, | |
208 message + 8, attr); | |
209 break; | |
210 case SSH_FILEXFER_ATTR_ACMODTIME: | |
211 request->logging_function (level, request->user_data, | |
212 _("%d: Utime %s %d\n"), id, | |
213 message + 8, attr); | |
214 } | |
215 *pos = oldchar; | |
216 break; | |
217 case SSH_FXP_STATUS: | |
218 if (params->dont_log_status) | |
219 break; | |
220 memcpy (&num, message + 4, 4); | |
221 num = ntohl (num); | |
222 switch (num) | |
223 { | |
224 case SSH_FX_OK: | |
225 descr = _("OK"); | |
226 break; | |
227 case SSH_FX_EOF: | |
228 descr = _("EOF"); | |
229 break; | |
230 case SSH_FX_NO_SUCH_FILE: | |
231 descr = _("No such file or directory"); | |
232 break; | |
233 case SSH_FX_PERMISSION_DENIED: | |
234 descr = _("Permission denied"); | |
235 break; | |
236 case SSH_FX_FAILURE: | |
237 descr = _("Failure"); | |
238 break; | |
239 case SSH_FX_BAD_MESSAGE: | |
240 descr = _("Bad message"); | |
241 break; | |
242 case SSH_FX_NO_CONNECTION: | |
243 descr = _("No connection"); | |
244 break; | |
245 case SSH_FX_CONNECTION_LOST: | |
246 descr = _("Connection lost"); | |
247 break; | |
248 case SSH_FX_OP_UNSUPPORTED: | |
249 descr = _("Operation unsupported"); | |
250 break; | |
251 default: | |
252 descr = _("Unknown message returned from server"); | |
253 break; | |
254 } | |
255 request->logging_function (level, request->user_data, | |
256 "%d: %s\n", id, descr); | |
257 break; | |
258 case SSH_FXP_HANDLE: | |
259 request->logging_function (level, request->user_data, | |
260 "%d: File handle\n", id); | |
261 break; | |
262 case SSH_FXP_DATA: | |
263 break; | |
264 case SSH_FXP_NAME: | |
265 memcpy (&num, message + 4, 4); | |
266 num = ntohl (num); | |
267 request->logging_function (level, request->user_data, | |
268 "%d: Filenames (%d entries)\n", id, | |
269 num); | |
270 break; | |
271 default: | |
272 request->logging_function (level, request->user_data, | |
273 "Command: %x\n", type); | |
274 } | |
275 } | |
1 | 276 |
48 | 277 |
278 static int | |
279 sshv2_send_command (gftp_request * request, char type, char *command, | |
280 gint32 len) | |
281 { | |
282 char buf[34000]; | |
283 gint32 clen; | |
284 | |
285 if (len > 33995) | |
286 { | |
287 request->logging_function (gftp_logging_error, request->user_data, | |
288 _("Error: Message size %d too big\n"), len); | |
289 gftp_disconnect (request); | |
290 return (-1); | |
291 } | |
292 | |
293 clen = htonl (len + 1); | |
294 memcpy (buf, &clen, 4); | |
295 buf[4] = type; | |
296 memcpy (&buf[5], command, len); | |
297 buf[len + 5] = '\0'; | |
298 | |
299 #ifdef DEBUG | |
300 printf ("\rSending: "); | |
301 for (wrote=0; wrote<len + 5; wrote++) | |
302 printf ("%x ", buf[wrote]); | |
303 printf ("\n"); | |
304 #endif | |
305 | |
306 sshv2_log_command (request, gftp_logging_send, type, buf + 5, len); | |
307 | |
308 if (gftp_fwrite (request, buf, len + 5, request->sockfd_write) < 0) | |
309 return (-2); | |
310 | |
311 return 0; | |
312 } | |
313 | |
314 | |
315 static int | |
316 sshv2_read_response (gftp_request * request, sshv2_message * message, | |
317 FILE * fd) | |
318 { | |
319 ssize_t numread; | |
320 char buf[5]; | |
321 | |
322 if (fd == NULL) | |
323 fd = request->sockfd; | |
1 | 324 |
48 | 325 numread = fread (buf, 5, 1, fd); |
326 if (ferror (fd)) | |
327 { | |
328 request->logging_function (gftp_logging_error, request->user_data, | |
329 _("Error: Could not read from socket: %s\n"), | |
330 g_strerror (errno)); | |
331 gftp_disconnect (request); | |
332 return (-1); | |
333 } | |
334 | |
335 #ifdef DEBUG | |
336 printf ("\rReceived: "); | |
337 for (numread=0; numread<5; numread++) | |
338 printf ("%x ", buf[numread]); | |
339 fflush (stdout); | |
340 #endif | |
341 | |
342 memcpy (&message->length, buf, 4); | |
343 message->length = ntohl (message->length); | |
344 if (message->length > 34000) | |
345 { | |
346 request->logging_function (gftp_logging_error, request->user_data, | |
347 _("Error: Message size %d too big from server\n"), | |
348 message->length); | |
349 memset (message, 0, sizeof (*message)); | |
350 gftp_disconnect (request); | |
351 return (-1); | |
352 } | |
353 message->command = buf[4]; | |
354 message->buffer = g_malloc (message->length); | |
355 | |
356 message->pos = message->buffer; | |
357 message->end = message->buffer + message->length - 1; | |
358 | |
359 numread = fread (message->buffer, message->length - 1, 1, fd); | |
360 if (ferror (fd)) | |
361 { | |
362 request->logging_function (gftp_logging_error, request->user_data, | |
363 _("Error: Could not read from socket: %s\n"), | |
364 g_strerror (errno)); | |
365 gftp_disconnect (request); | |
366 return (-1); | |
367 } | |
368 message->buffer[message->length - 1] = '\0'; | |
369 | |
370 #ifdef DEBUG | |
371 printf ("\rReceived: "); | |
372 for (numread=0; numread<message->length - 1; numread++) | |
373 printf ("%x ", message->buffer[numread]); | |
374 printf ("\n"); | |
375 #endif | |
376 | |
377 sshv2_log_command (request, gftp_logging_recv, message->command, | |
378 message->buffer, message->length); | |
379 | |
380 return (message->command); | |
1 | 381 } |
382 | |
383 | |
384 static void | |
385 sshv2_destroy (gftp_request * request) | |
386 { | |
387 g_return_if_fail (request != NULL); | |
388 g_return_if_fail (request->protonum == GFTP_SSHV2_NUM); | |
389 | |
390 g_free (request->protocol_data); | |
391 request->protocol_data = NULL; | |
392 } | |
393 | |
394 | |
48 | 395 static void |
396 sshv2_message_free (sshv2_message * message) | |
397 { | |
398 if (message->buffer) | |
399 g_free (message->buffer); | |
400 memset (message, 0, sizeof (*message)); | |
401 } | |
402 | |
403 | |
404 static gint32 | |
405 sshv2_buffer_get_int32 (gftp_request * request, sshv2_message * message, | |
406 int expected_response) | |
407 { | |
408 gint32 ret; | |
409 | |
410 if (message->end - message->pos < 4) | |
411 { | |
412 request->logging_function (gftp_logging_error, request->user_data, | |
413 _("Received wrong response from server, disconnecting\n")); | |
414 sshv2_message_free (message); | |
415 gftp_disconnect (request); | |
416 return (-2); | |
417 } | |
418 | |
419 memcpy (&ret, message->pos, 4); | |
420 ret = ntohl (ret); | |
421 message->pos += 4; | |
422 | |
423 if (expected_response > 0 && ret != expected_response) | |
424 { | |
425 request->logging_function (gftp_logging_error, request->user_data, | |
426 _("Received wrong response from server, disconnecting\n")); | |
427 sshv2_message_free (message); | |
428 gftp_disconnect (request); | |
429 return (-2); | |
430 } | |
431 | |
432 return (ret); | |
433 } | |
434 | |
435 | |
436 static char * | |
437 sshv2_buffer_get_string (gftp_request * request, sshv2_message * message) | |
438 { | |
439 char *string; | |
440 gint32 len; | |
441 | |
442 if ((len = sshv2_buffer_get_int32 (request, message, -1)) < 0) | |
443 return (NULL); | |
444 | |
445 if (len > SSH_MAX_STRING_SIZE || (message->end - message->pos < len)) | |
446 { | |
447 request->logging_function (gftp_logging_error, request->user_data, | |
448 _("Received wrong response from server, disconnecting\n")); | |
449 sshv2_message_free (message); | |
450 gftp_disconnect (request); | |
451 return (NULL); | |
452 } | |
453 | |
454 string = g_malloc (len + 1); | |
455 memcpy (string, message->pos, len); | |
456 string[len] = '\0'; | |
457 message->pos += len; | |
458 return (string); | |
459 } | |
460 | |
461 | |
462 static int | |
463 sshv2_getcwd (gftp_request * request) | |
464 { | |
465 sshv2_message message; | |
466 sshv2_params * params; | |
467 char *tempstr, *dir; | |
468 gint32 num; | |
469 size_t len; | |
470 | |
471 g_return_val_if_fail (request != NULL, -2); | |
472 g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2); | |
473 | |
474 if (request->directory == NULL || *request->directory == '\0') | |
475 dir = "."; | |
476 else | |
477 dir = request->directory; | |
478 | |
479 params = request->protocol_data; | |
480 len = strlen (dir); | |
481 tempstr = g_malloc (len + 9); | |
482 strcpy (tempstr + 8, dir); | |
483 | |
484 num = htonl (params->id++); | |
485 memcpy (tempstr, &num, 4); | |
486 | |
487 num = htonl (len); | |
488 memcpy (tempstr + 4, &num, 4); | |
489 if (sshv2_send_command (request, SSH_FXP_REALPATH, tempstr, len + 8) < 0) | |
490 { | |
491 g_free (tempstr); | |
492 return (-2); | |
493 } | |
494 | |
495 g_free (tempstr); | |
496 if (request->directory) | |
497 { | |
498 g_free (request->directory); | |
499 request->directory = NULL; | |
500 } | |
501 | |
502 memset (&message, 0, sizeof (message)); | |
503 if (sshv2_read_response (request, &message, NULL) != SSH_FXP_NAME) | |
504 { | |
505 request->logging_function (gftp_logging_error, request->user_data, | |
506 _("Received wrong response from server, disconnecting\n")); | |
507 sshv2_message_free (&message); | |
508 gftp_disconnect (request); | |
509 return (-2); | |
510 } | |
511 | |
512 message.pos += 4; | |
513 if (sshv2_buffer_get_int32 (request, &message, 1) < 0) | |
514 return (-2); | |
515 | |
516 if ((request->directory = sshv2_buffer_get_string (request, &message)) == NULL) | |
517 return (-2); | |
518 sshv2_message_free (&message); | |
519 return (0); | |
520 } | |
521 | |
522 | |
1 | 523 static int |
524 sshv2_connect (gftp_request * request) | |
525 { | |
526 char **args, *tempstr, pts_name[20], *p1, p2, *exepath, port[6]; | |
527 int version, fdm, fds, s[2]; | |
528 sshv2_message message; | |
529 const gchar *errstr; | |
530 pid_t child; | |
531 | |
532 g_return_val_if_fail (request != NULL, -2); | |
533 g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2); | |
534 g_return_val_if_fail (request->hostname != NULL, -2); | |
535 | |
536 if (request->sockfd != NULL) | |
537 return (0); | |
538 | |
539 request->logging_function (gftp_logging_misc, request->user_data, | |
540 _("Opening SSH connection to %s\n"), | |
541 request->hostname); | |
542 | |
543 /* Ugh!! We don't get a login banner from sftp-server, and if we are | |
544 using ssh-agent to cache a users password, then we won't receive | |
545 any initial text from the server, and we'll block. So I just send a | |
546 xsftp server banner over. I hope this works on most Unices */ | |
547 | |
548 if (request->sftpserv_path == NULL || | |
549 *request->sftpserv_path == '\0') | |
550 { | |
551 p1 = ""; | |
552 p2 = ' '; | |
553 } | |
554 else | |
555 { | |
556 p1 = request->sftpserv_path; | |
557 p2 = '/'; | |
558 } | |
559 | |
560 *port = '\0'; | |
561 exepath = g_strdup_printf ("echo -n xsftp ; %s%csftp-server", p1, p2); | |
562 args = make_ssh_exec_args (request, exepath, sshv2_use_sftp_subsys, port); | |
563 | |
564 if (ssh_use_askpass || sshv2_use_sftp_subsys) | |
565 { | |
566 fdm = fds = 0; | |
567 if (socketpair (AF_LOCAL, SOCK_STREAM, 0, s) < 0) | |
568 { | |
569 request->logging_function (gftp_logging_error, request->user_data, | |
570 _("Cannot create a socket pair: %s\n"), | |
571 g_strerror (errno)); | |
572 return (-2); | |
573 } | |
574 } | |
575 else | |
576 { | |
577 s[0] = s[1] = 0; | |
578 if ((fdm = ptym_open (pts_name)) < 0) | |
579 { | |
580 request->logging_function (gftp_logging_error, request->user_data, | |
581 _("Cannot open master pty %s: %s\n"), pts_name, | |
582 g_strerror (errno)); | |
583 return (-2); | |
584 } | |
585 } | |
586 | |
587 if ((child = fork ()) == 0) | |
588 { | |
589 setsid (); | |
590 if (ssh_use_askpass || sshv2_use_sftp_subsys) | |
591 { | |
592 close (s[0]); | |
593 fds = s[1]; | |
594 } | |
595 else | |
596 { | |
597 if ((fds = ptys_open (fdm, pts_name)) < 0) | |
598 { | |
599 printf ("Cannot open slave pts %s: %s\n", pts_name, | |
600 g_strerror (errno)); | |
601 return (-1); | |
602 } | |
603 close (fdm); | |
604 } | |
605 | |
606 tty_raw (fds); | |
607 dup2 (fds, 0); | |
608 dup2 (fds, 1); | |
609 dup2 (fds, 2); | |
610 if (!ssh_use_askpass && fds > 2) | |
611 close (fds); | |
612 execvp (ssh_prog_name != NULL && *ssh_prog_name != '\0' ? | |
613 ssh_prog_name : "ssh", args); | |
614 | |
615 tempstr = _("Error: Cannot execute ssh: "); | |
616 write (1, tempstr, strlen (tempstr)); | |
617 errstr = g_strerror (errno); | |
618 write (1, errstr, strlen (errstr)); | |
619 write (1, "\n", 1); | |
620 return (-1); | |
621 } | |
622 else if (child > 0) | |
623 { | |
624 if (ssh_use_askpass || sshv2_use_sftp_subsys) | |
625 { | |
626 close (s[1]); | |
627 fdm = s[0]; | |
628 } | |
629 tty_raw (fdm); | |
630 if (!sshv2_use_sftp_subsys) | |
631 { | |
632 tempstr = ssh_start_login_sequence (request, fdm); | |
633 if (!tempstr || | |
634 !(strlen (tempstr) > 4 && strcmp (tempstr + strlen (tempstr) - 5, | |
635 "xsftp") == 0)) | |
636 { | |
637 request->logging_function (gftp_logging_error, request->user_data, | |
638 _("Error: Received wrong init string from server\n")); | |
639 g_free (args); | |
640 g_free (exepath); | |
641 return (-2); | |
642 } | |
643 g_free (tempstr); | |
644 } | |
645 g_free (args); | |
646 g_free (exepath); | |
647 | |
14
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
1
diff
changeset
|
648 if ((request->sockfd = fdopen (fdm, "rb+")) == NULL) |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
1
diff
changeset
|
649 { |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
1
diff
changeset
|
650 request->logging_function (gftp_logging_error, request->user_data, |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
1
diff
changeset
|
651 _("Cannot fdopen() socket: %s\n"), |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
1
diff
changeset
|
652 g_strerror (errno)); |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
1
diff
changeset
|
653 close (fdm); |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
1
diff
changeset
|
654 return (-2); |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
1
diff
changeset
|
655 } |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
1
diff
changeset
|
656 |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
1
diff
changeset
|
657 if ((request->sockfd_write = fdopen (fdm, "wb+")) == NULL) |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
1
diff
changeset
|
658 { |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
1
diff
changeset
|
659 request->logging_function (gftp_logging_error, request->user_data, |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
1
diff
changeset
|
660 _("Cannot fdopen() socket: %s\n"), |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
1
diff
changeset
|
661 g_strerror (errno)); |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
1
diff
changeset
|
662 gftp_disconnect (request); |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
1
diff
changeset
|
663 return (-2); |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
1
diff
changeset
|
664 } |
1 | 665 |
666 version = htonl (SSH_MY_VERSION); | |
667 if (sshv2_send_command (request, SSH_FXP_INIT, (char *) &version, 4) < 0) | |
668 return (-2); | |
669 | |
670 memset (&message, 0, sizeof (message)); | |
671 if (sshv2_read_response (request, &message, NULL) != SSH_FXP_VERSION) | |
672 { | |
673 request->logging_function (gftp_logging_error, request->user_data, | |
674 _("Received wrong response from server, disconnecting\n")); | |
675 sshv2_message_free (&message); | |
676 gftp_disconnect (request); | |
677 return (-2); | |
678 } | |
679 sshv2_message_free (&message); | |
680 | |
681 request->logging_function (gftp_logging_misc, request->user_data, | |
682 _("Successfully logged into SSH server %s\n"), | |
683 request->hostname); | |
684 } | |
685 else | |
686 { | |
687 request->logging_function (gftp_logging_error, request->user_data, | |
688 _("Cannot fork another process: %s\n"), | |
689 g_strerror (errno)); | |
690 g_free (args); | |
691 return (-1); | |
692 } | |
693 | |
694 sshv2_getcwd (request); | |
695 if (request->sockfd == NULL) | |
696 return (-2); | |
697 | |
698 return (0); | |
699 } | |
700 | |
701 | |
702 static void | |
703 sshv2_disconnect (gftp_request * request) | |
704 { | |
705 sshv2_params * params; | |
706 | |
707 g_return_if_fail (request != NULL); | |
708 g_return_if_fail (request->protonum == GFTP_SSHV2_NUM); | |
709 | |
710 params = request->protocol_data; | |
711 | |
712 if (request->sockfd != NULL) | |
713 { | |
714 request->logging_function (gftp_logging_misc, request->user_data, | |
715 _("Disconnecting from site %s\n"), | |
716 request->hostname); | |
717 fclose (request->sockfd); | |
14
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
1
diff
changeset
|
718 request->sockfd = request->sockfd_write = NULL; |
1 | 719 } |
720 | |
721 if (params->message.buffer != NULL) | |
722 sshv2_message_free (¶ms->message); | |
723 } | |
724 | |
725 | |
726 static int | |
727 sshv2_end_transfer (gftp_request * request) | |
728 { | |
729 sshv2_params * params; | |
730 sshv2_message message; | |
731 gint32 len; | |
732 | |
733 g_return_val_if_fail (request != NULL, -2); | |
734 g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2); | |
735 | |
736 params = request->protocol_data; | |
737 if (params->message.buffer != NULL) | |
738 { | |
739 sshv2_message_free (¶ms->message); | |
740 params->count = 0; | |
741 } | |
742 | |
743 if (params->handle_len > 0) | |
744 { | |
745 len = htonl (params->id++); | |
746 memcpy (params->handle, &len, 4); | |
747 | |
748 if (sshv2_send_command (request, SSH_FXP_CLOSE, params->handle, | |
749 params->handle_len) < 0) | |
750 return (-2); | |
751 | |
752 memset (&message, 0, sizeof (message)); | |
753 if (sshv2_read_response (request, &message, NULL) != SSH_FXP_STATUS) | |
754 { | |
755 request->logging_function (gftp_logging_error, request->user_data, | |
756 _("Received wrong response from server, disconnecting\n")); | |
757 sshv2_message_free (&message); | |
758 gftp_disconnect (request); | |
759 return (-2); | |
760 } | |
761 sshv2_message_free (&message); | |
762 params->handle_len = 0; | |
763 } | |
764 | |
765 if (params->read_buffer != NULL) | |
766 { | |
767 g_free (params->read_buffer); | |
768 params->read_buffer = NULL; | |
769 } | |
770 | |
771 return (0); | |
772 } | |
773 | |
774 | |
775 static int | |
776 sshv2_list_files (gftp_request * request) | |
777 { | |
778 sshv2_params * params; | |
779 sshv2_message message; | |
780 char *tempstr; | |
781 gint32 len; | |
782 | |
783 g_return_val_if_fail (request != NULL, -2); | |
784 g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2); | |
785 g_return_val_if_fail (request->sockfd != NULL, -2); | |
786 | |
787 params = request->protocol_data; | |
788 | |
789 request->logging_function (gftp_logging_misc, request->user_data, | |
790 _("Retrieving directory listing...\n")); | |
791 | |
792 tempstr = g_malloc (strlen (request->directory) + 9); | |
793 | |
794 len = htonl (params->id++); | |
795 memcpy (tempstr, &len, 4); | |
796 | |
797 len = htonl (strlen (request->directory)); | |
798 memcpy (tempstr + 4, &len, 4); | |
799 strcpy (tempstr + 8, request->directory); | |
800 if (sshv2_send_command (request, SSH_FXP_OPENDIR, tempstr, | |
801 strlen (request->directory) + 8) < 0) | |
802 { | |
803 g_free (tempstr); | |
804 return (-2); | |
805 } | |
806 g_free (tempstr); | |
807 | |
808 memset (&message, 0, sizeof (message)); | |
809 if (sshv2_read_response (request, &message, NULL) != SSH_FXP_HANDLE) | |
810 { | |
811 request->logging_function (gftp_logging_error, request->user_data, | |
812 _("Received wrong response from server, disconnecting\n")); | |
813 sshv2_message_free (&message); | |
814 gftp_disconnect (request); | |
815 return (-2); | |
816 } | |
817 | |
818 if (message.length - 4 > SSH_MAX_HANDLE_SIZE) | |
819 { | |
820 request->logging_function (gftp_logging_error, request->user_data, | |
821 _("Error: Message size %d too big from server\n"), | |
822 message.length - 4); | |
823 sshv2_message_free (&message); | |
824 gftp_disconnect (request); | |
825 return (-1); | |
826 | |
827 } | |
828 | |
829 memset (params->handle, 0, 4); | |
830 memcpy (params->handle + 4, message.buffer + 4, message.length - 5); | |
831 params->handle_len = message.length - 1; | |
832 sshv2_message_free (&message); | |
833 params->count = 0; | |
834 return (0); | |
835 } | |
836 | |
837 | |
838 static int | |
839 sshv2_get_next_file (gftp_request * request, gftp_file * fle, FILE * fd) | |
840 { | |
841 gint32 len, attrs, longnamelen; | |
842 int ret, i, count, retsize; | |
843 sshv2_params *params; | |
844 char *longname; | |
845 | |
846 g_return_val_if_fail (request != NULL, -2); | |
847 g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2); | |
848 g_return_val_if_fail (fle != NULL, -2); | |
849 | |
850 params = request->protocol_data; | |
851 | |
852 if (request->last_dir_entry) | |
853 { | |
854 g_free (request->last_dir_entry); | |
855 request->last_dir_entry = NULL; | |
856 request->last_dir_entry_len = 0; | |
857 } | |
858 retsize = 0; | |
859 | |
860 if (params->count > 0) | |
861 ret = SSH_FXP_NAME; | |
862 else | |
863 { | |
864 if (!request->cached) | |
865 { | |
866 if (params->message.buffer != NULL) | |
867 sshv2_message_free (¶ms->message); | |
868 | |
869 len = htonl (params->id++); | |
870 memcpy (params->handle, &len, 4); | |
871 | |
872 if (sshv2_send_command (request, SSH_FXP_READDIR, params->handle, | |
873 params->handle_len) < 0) | |
874 return (-2); | |
875 } | |
876 | |
877 if ((ret = sshv2_read_response (request, ¶ms->message, fd)) < 0) | |
878 return (-2); | |
879 | |
880 if (!request->cached) | |
881 { | |
882 request->last_dir_entry = g_malloc (params->message.length + 4); | |
883 len = htonl (params->message.length); | |
884 memcpy (request->last_dir_entry, &len, 4); | |
885 request->last_dir_entry[4] = params->message.command; | |
886 memcpy (request->last_dir_entry + 5, params->message.buffer, | |
887 params->message.length - 1); | |
888 request->last_dir_entry_len = params->message.length + 4; | |
889 } | |
890 | |
891 if (ret == SSH_FXP_NAME) | |
892 { | |
893 params->message.pos = params->message.buffer + 4; | |
894 if ((params->count = sshv2_buffer_get_int32 (request, | |
895 ¶ms->message, -1)) < 0) | |
896 return (-2); | |
897 } | |
898 } | |
899 | |
900 if (ret == SSH_FXP_NAME) | |
901 { | |
902 if ((len = sshv2_buffer_get_int32 (request, ¶ms->message, -1)) < 0 || | |
903 params->message.pos + len > params->message.end) | |
904 return (-2); | |
905 | |
906 params->message.pos += len; | |
907 | |
908 if ((longnamelen = sshv2_buffer_get_int32 (request, | |
909 ¶ms->message, -1)) < 0 || | |
910 params->message.pos + longnamelen > params->message.end) | |
911 return (-2); | |
912 | |
913 longname = params->message.pos; | |
914 params->message.pos += longnamelen; | |
915 | |
916 if ((attrs = sshv2_buffer_get_int32 (request, ¶ms->message, -1)) < 0) | |
917 return (-2); | |
918 | |
919 if (attrs & SSH_FILEXFER_ATTR_SIZE) | |
920 { | |
921 params->message.pos += 8; | |
922 if (params->message.pos > params->message.end) | |
923 { | |
924 request->logging_function (gftp_logging_error, request->user_data, | |
925 _("Received wrong response from server, disconnecting\n")); | |
926 sshv2_message_free (¶ms->message); | |
927 gftp_disconnect (request); | |
928 return (-2); | |
929 } | |
930 } | |
931 | |
932 if (attrs & SSH_FILEXFER_ATTR_UIDGID) | |
933 { | |
934 params->message.pos += 8; | |
935 if (params->message.pos > params->message.end) | |
936 { | |
937 request->logging_function (gftp_logging_error, request->user_data, | |
938 _("Received wrong response from server, disconnecting\n")); | |
939 sshv2_message_free (¶ms->message); | |
940 gftp_disconnect (request); | |
941 return (-2); | |
942 } | |
943 } | |
944 | |
945 if (attrs & SSH_FILEXFER_ATTR_PERMISSIONS) | |
946 { | |
947 params->message.pos += 4; | |
948 if (params->message.pos > params->message.end) | |
949 { | |
950 request->logging_function (gftp_logging_error, request->user_data, | |
951 _("Received wrong response from server, disconnecting\n")); | |
952 sshv2_message_free (¶ms->message); | |
953 gftp_disconnect (request); | |
954 return (-2); | |
955 } | |
956 } | |
957 | |
958 if (attrs & SSH_FILEXFER_ATTR_ACMODTIME) | |
959 { | |
960 params->message.pos += 8; | |
961 if (params->message.pos > params->message.end) | |
962 { | |
963 request->logging_function (gftp_logging_error, request->user_data, | |
964 _("Received wrong response from server, disconnecting\n")); | |
965 sshv2_message_free (¶ms->message); | |
966 gftp_disconnect (request); | |
967 return (-2); | |
968 } | |
969 } | |
970 | |
971 if (attrs & SSH_FILEXFER_ATTR_EXTENDED) | |
972 { | |
973 if ((count = sshv2_buffer_get_int32 (request, | |
974 ¶ms->message, -1)) < 0) | |
975 return (-2); | |
976 | |
977 for (i=0; i<count; i++) | |
978 { | |
979 if ((len = sshv2_buffer_get_int32 (request, | |
980 ¶ms->message, -1)) < 0 || | |
981 params->message.pos + len + 4 > params->message.end) | |
982 return (-2); | |
983 | |
984 params->message.pos += len + 4; | |
985 | |
986 if ((len = sshv2_buffer_get_int32 (request, | |
987 ¶ms->message, -1)) < 0 || | |
988 params->message.pos + len + 4 > params->message.end) | |
989 return (-2); | |
990 | |
991 params->message.pos += len + 4; | |
992 } | |
993 } | |
994 | |
995 longname[longnamelen] = '\0'; | |
996 | |
997 /* The commercial SSH2 puts a / and * after some entries */ | |
998 if (longname[longnamelen - 1] == '*') | |
999 longname[--longnamelen] = '\0'; | |
1000 if (longname[longnamelen - 1] == '/') | |
1001 longname[--longnamelen] = '\0'; | |
1002 | |
1003 if (gftp_parse_ls (longname, fle) != 0) | |
1004 { | |
1005 gftp_file_destroy (fle); | |
1006 return (-2); | |
1007 } | |
1008 retsize = strlen (longname); | |
1009 | |
1010 params->count--; | |
1011 } | |
1012 else if (ret == SSH_FXP_STATUS) | |
1013 { | |
1014 sshv2_message_free (¶ms->message); | |
1015 return (0); | |
1016 } | |
1017 else | |
1018 { | |
1019 request->logging_function (gftp_logging_error, request->user_data, | |
1020 _("Received wrong response from server, disconnecting\n")); | |
1021 sshv2_message_free (¶ms->message); | |
1022 gftp_disconnect (request); | |
1023 return (-2); | |
1024 } | |
1025 | |
1026 return (retsize); | |
1027 } | |
1028 | |
1029 | |
1030 static int | |
1031 sshv2_chdir (gftp_request * request, const char *directory) | |
1032 { | |
1033 sshv2_message message; | |
1034 sshv2_params * params; | |
1035 char *tempstr, *dir; | |
1036 gint32 num; | |
1037 size_t len; | |
1038 | |
1039 g_return_val_if_fail (request != NULL, -2); | |
1040 g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2); | |
1041 | |
1042 params = request->protocol_data; | |
1043 if (request->directory != directory) | |
1044 { | |
1045 if (*directory == '/') | |
1046 { | |
1047 len = strlen (directory) + 8; | |
1048 tempstr = g_malloc (len + 1); | |
1049 strcpy (tempstr + 8, directory); | |
1050 } | |
1051 else | |
1052 { | |
1053 len = strlen (directory) + strlen (request->directory) + 9; | |
1054 tempstr = g_malloc (len + 1); | |
1055 strcpy (tempstr + 8, request->directory); | |
1056 strcat (tempstr + 8, "/"); | |
1057 strcat (tempstr + 8, directory); | |
1058 } | |
1059 | |
1060 num = htonl (params->id++); | |
1061 memcpy (tempstr, &num, 4); | |
1062 | |
1063 num = htonl (len - 8); | |
1064 memcpy (tempstr + 4, &num, 4); | |
1065 if (sshv2_send_command (request, SSH_FXP_REALPATH, tempstr, len) < 0) | |
1066 { | |
1067 g_free (tempstr); | |
1068 return (-2); | |
1069 } | |
1070 g_free (tempstr); | |
1071 | |
1072 memset (&message, 0, sizeof (message)); | |
1073 if (sshv2_read_response (request, &message, NULL) != SSH_FXP_NAME) | |
1074 { | |
1075 request->logging_function (gftp_logging_error, request->user_data, | |
1076 _("Received wrong response from server, disconnecting\n")); | |
1077 sshv2_message_free (&message); | |
1078 gftp_disconnect (request); | |
1079 return (-2); | |
1080 } | |
1081 | |
1082 message.pos += 4; | |
1083 if (sshv2_buffer_get_int32 (request, &message, 1) != 1) | |
1084 return (-2); | |
1085 | |
1086 if ((dir = sshv2_buffer_get_string (request, &message)) == NULL) | |
1087 return (-2); | |
1088 | |
1089 if (request->directory) | |
1090 g_free (request->directory); | |
1091 request->directory = dir; | |
1092 sshv2_message_free (&message); | |
1093 } | |
1094 | |
1095 return (0); | |
1096 } | |
1097 | |
1098 | |
1099 static int | |
1100 sshv2_rmdir (gftp_request * request, const char *directory) | |
1101 { | |
1102 sshv2_params * params; | |
1103 sshv2_message message; | |
1104 char *tempstr; | |
1105 gint32 num; | |
1106 size_t len; | |
1107 | |
1108 g_return_val_if_fail (request != NULL, -2); | |
1109 g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2); | |
1110 g_return_val_if_fail (directory != NULL, -2); | |
1111 | |
1112 params = request->protocol_data; | |
1113 | |
1114 if (*directory == '/') | |
1115 { | |
1116 len = strlen (directory) + 8; | |
1117 tempstr = g_malloc (len + 1); | |
1118 strcpy (tempstr + 8, directory); | |
1119 } | |
1120 else | |
1121 { | |
1122 len = strlen (directory) + strlen (request->directory) + 9; | |
1123 tempstr = g_malloc (len + 1); | |
1124 strcpy (tempstr + 8, request->directory); | |
1125 strcat (tempstr + 8, "/"); | |
1126 strcat (tempstr + 8, directory); | |
1127 } | |
1128 | |
1129 num = htonl (params->id++); | |
1130 memcpy (tempstr, &num, 4); | |
1131 | |
1132 num = htonl (len - 8); | |
1133 memcpy (tempstr + 4, &num, 4); | |
1134 | |
1135 if (sshv2_send_command (request, SSH_FXP_RMDIR, tempstr, len) < 0) | |
1136 { | |
1137 g_free (tempstr); | |
1138 return (-2); | |
1139 } | |
1140 g_free (tempstr); | |
1141 | |
1142 memset (&message, 0, sizeof (message)); | |
1143 if (sshv2_read_response (request, &message, NULL) < 0) | |
1144 return (-2); | |
1145 | |
1146 message.pos += 4; | |
1147 if (sshv2_buffer_get_int32 (request, &message, SSH_FX_OK) < 0) | |
1148 return (-2); | |
1149 | |
1150 sshv2_message_free (&message); | |
1151 | |
1152 return (0); | |
1153 } | |
1154 | |
1155 | |
1156 static int | |
1157 sshv2_rmfile (gftp_request * request, const char *file) | |
1158 { | |
1159 sshv2_params * params; | |
1160 sshv2_message message; | |
1161 char *tempstr; | |
1162 gint32 num; | |
1163 size_t len; | |
1164 | |
1165 g_return_val_if_fail (request != NULL, -2); | |
1166 g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2); | |
1167 g_return_val_if_fail (file != NULL, -2); | |
1168 | |
1169 params = request->protocol_data; | |
1170 | |
1171 if (*file == '/') | |
1172 { | |
1173 len = strlen (file) + 8; | |
1174 tempstr = g_malloc (len + 1); | |
1175 strcpy (tempstr + 8, file); | |
1176 } | |
1177 else | |
1178 { | |
1179 len = strlen (file) + strlen (request->directory) + 9; | |
1180 tempstr = g_malloc (len + 1); | |
1181 strcpy (tempstr + 8, request->directory); | |
1182 strcat (tempstr + 8, "/"); | |
1183 strcat (tempstr + 8, file); | |
1184 } | |
1185 | |
1186 num = htonl (params->id++); | |
1187 memcpy (tempstr, &num, 4); | |
1188 | |
1189 num = htonl (len - 8); | |
1190 memcpy (tempstr + 4, &num, 4); | |
1191 | |
1192 if (sshv2_send_command (request, SSH_FXP_REMOVE, tempstr, len) < 0) | |
1193 { | |
1194 g_free (tempstr); | |
1195 return (-2); | |
1196 } | |
1197 g_free (tempstr); | |
1198 | |
1199 memset (&message, 0, sizeof (message)); | |
1200 if (sshv2_read_response (request, &message, NULL) < 0) | |
1201 return (-2); | |
1202 | |
1203 message.pos += 4; | |
1204 if (sshv2_buffer_get_int32 (request, &message, SSH_FX_OK) < 0) | |
1205 return (-2); | |
1206 | |
1207 sshv2_message_free (&message); | |
1208 | |
1209 return (0); | |
1210 } | |
1211 | |
1212 | |
1213 static int | |
1214 sshv2_chmod (gftp_request * request, const char *file, int mode) | |
1215 { | |
1216 char *tempstr, buf[10]; | |
1217 sshv2_params * params; | |
1218 sshv2_message message; | |
1219 gint32 num; | |
1220 size_t len; | |
1221 | |
1222 g_return_val_if_fail (request != NULL, -2); | |
1223 g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2); | |
1224 g_return_val_if_fail (file != NULL, -2); | |
1225 | |
1226 params = request->protocol_data; | |
1227 | |
1228 if (*file == '/') | |
1229 { | |
1230 len = strlen (file) + 16; | |
1231 tempstr = g_malloc (len + 1); | |
1232 strcpy (tempstr + 8, file); | |
1233 } | |
1234 else | |
1235 { | |
1236 len = strlen (file) + strlen (request->directory) + 17; | |
1237 tempstr = g_malloc (len + 1); | |
1238 strcpy (tempstr + 8, request->directory); | |
1239 strcat (tempstr + 8, "/"); | |
1240 strcat (tempstr + 8, file); | |
1241 } | |
1242 | |
1243 num = htonl (params->id++); | |
1244 memcpy (tempstr, &num, 4); | |
1245 | |
1246 num = htonl (len - 16); | |
1247 memcpy (tempstr + 4, &num, 4); | |
1248 | |
1249 num = htonl (SSH_FILEXFER_ATTR_PERMISSIONS); | |
1250 memcpy (tempstr + len - 8, &num, 4); | |
1251 | |
1252 g_snprintf (buf, sizeof (buf), "%d", mode); | |
1253 num = htonl (strtol (buf, NULL, 8)); | |
1254 memcpy (tempstr + len - 4, &num, 4); | |
1255 | |
1256 if (sshv2_send_command (request, SSH_FXP_SETSTAT, tempstr, len) < 0) | |
1257 { | |
1258 g_free (tempstr); | |
1259 return (-2); | |
1260 } | |
1261 g_free (tempstr); | |
1262 | |
1263 memset (&message, 0, sizeof (message)); | |
1264 if (sshv2_read_response (request, &message, NULL) < 0) | |
1265 return (-2); | |
1266 | |
1267 message.pos += 4; | |
1268 if (sshv2_buffer_get_int32 (request, &message, SSH_FX_OK) < 0) | |
1269 return (-2); | |
1270 | |
1271 sshv2_message_free (&message); | |
1272 | |
1273 return (0); | |
1274 } | |
1275 | |
1276 | |
1277 static int | |
1278 sshv2_mkdir (gftp_request * request, const char *newdir) | |
1279 { | |
1280 sshv2_params * params; | |
1281 sshv2_message message; | |
1282 char *tempstr; | |
1283 gint32 num; | |
1284 size_t len; | |
1285 | |
1286 g_return_val_if_fail (request != NULL, -2); | |
1287 g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2); | |
1288 g_return_val_if_fail (newdir != NULL, -2); | |
1289 | |
1290 params = request->protocol_data; | |
1291 | |
1292 if (*newdir == '/') | |
1293 { | |
1294 len = strlen (newdir) + 12; | |
1295 tempstr = g_malloc (len + 1); | |
1296 strcpy (tempstr + 8, newdir); | |
1297 } | |
1298 else | |
1299 { | |
1300 len = strlen (newdir) + strlen (request->directory) + 13; | |
1301 tempstr = g_malloc (len + 1); | |
1302 strcpy (tempstr + 8, request->directory); | |
1303 strcat (tempstr + 8, "/"); | |
1304 strcat (tempstr + 8, newdir); | |
1305 } | |
1306 | |
1307 num = htonl (params->id++); | |
1308 memcpy (tempstr, &num, 4); | |
1309 | |
1310 num = htonl (len - 12); | |
1311 memcpy (tempstr + 4, &num, 4); | |
1312 memset (tempstr + len - 4, 0, 4); /* attributes */ | |
1313 | |
1314 if (sshv2_send_command (request, SSH_FXP_MKDIR, tempstr, len) < 0) | |
1315 { | |
1316 g_free (tempstr); | |
1317 return (-2); | |
1318 } | |
1319 g_free (tempstr); | |
1320 | |
1321 memset (&message, 0, sizeof (message)); | |
1322 if (sshv2_read_response (request, &message, NULL) < 0) | |
1323 return (-2); | |
1324 | |
1325 message.pos += 4; | |
1326 if (sshv2_buffer_get_int32 (request, &message, SSH_FX_OK) < 0) | |
1327 return (-2); | |
1328 | |
1329 sshv2_message_free (&message); | |
1330 | |
1331 return (0); | |
1332 } | |
1333 | |
1334 | |
1335 static int | |
1336 sshv2_rename (gftp_request * request, const char *oldname, const char *newname) | |
1337 { | |
1338 char *tempstr, *oldstr, *newstr; | |
1339 sshv2_params * params; | |
1340 sshv2_message message; | |
1341 gint32 num; | |
1342 size_t oldlen, newlen; | |
1343 | |
1344 g_return_val_if_fail (request != NULL, -2); | |
1345 g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2); | |
1346 g_return_val_if_fail (oldname != NULL, -2); | |
1347 g_return_val_if_fail (newname != NULL, -2); | |
1348 | |
1349 params = request->protocol_data; | |
1350 | |
1351 if (*oldname == '/') | |
1352 { | |
1353 oldlen = strlen (oldname); | |
56 | 1354 oldstr = g_strdup (oldname); |
1 | 1355 } |
1356 else | |
1357 { | |
1358 oldlen = strlen (request->directory) + strlen (oldname) + 1; | |
1359 oldstr = g_strconcat (request->directory, "/", oldname, NULL); | |
1360 } | |
1361 | |
1362 if (*newname == '/') | |
1363 { | |
1364 newlen = strlen (newname); | |
56 | 1365 newstr = g_strdup (newname); |
1 | 1366 } |
1367 else | |
1368 { | |
1369 newlen = strlen (request->directory) + strlen (newname) + 1; | |
1370 newstr = g_strconcat (request->directory, "/", newname, NULL); | |
1371 } | |
1372 | |
1373 tempstr = g_malloc (oldlen + newlen + 13); | |
1374 num = htonl (params->id++); | |
1375 memcpy (tempstr, &num, 4); | |
1376 | |
1377 num = htonl (oldlen); | |
1378 memcpy (tempstr + 4, &num, 4); | |
1379 strcpy (tempstr + 8, oldstr); | |
1380 | |
1381 num = htonl (newlen); | |
1382 memcpy (tempstr + 8 + oldlen, &num, 4); | |
1383 strcpy (tempstr + 12 + oldlen, newstr); | |
1384 | |
1385 if (sshv2_send_command (request, SSH_FXP_RENAME, tempstr, oldlen + newlen + 12) < 0) | |
1386 { | |
1387 g_free (tempstr); | |
1388 return (-2); | |
1389 } | |
1390 g_free (tempstr); | |
1391 | |
1392 memset (&message, 0, sizeof (message)); | |
1393 if (sshv2_read_response (request, &message, NULL) < 0) | |
1394 return (-2); | |
1395 | |
1396 message.pos += 4; | |
1397 if (sshv2_buffer_get_int32 (request, &message, SSH_FX_OK) < 0) | |
1398 return (-2); | |
1399 | |
1400 sshv2_message_free (&message); | |
1401 | |
1402 return (0); | |
1403 } | |
1404 | |
1405 | |
1406 static int | |
1407 sshv2_set_file_time (gftp_request * request, const char *file, time_t datetime) | |
1408 { | |
1409 sshv2_params * params; | |
1410 sshv2_message message; | |
1411 char *tempstr; | |
1412 gint32 num; | |
1413 size_t len; | |
1414 | |
1415 g_return_val_if_fail (request != NULL, -2); | |
1416 g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2); | |
1417 g_return_val_if_fail (file != NULL, -2); | |
1418 | |
1419 params = request->protocol_data; | |
1420 | |
1421 if (*file == '/') | |
1422 { | |
1423 len = strlen (file) + 20; | |
1424 tempstr = g_malloc (len + 1); | |
1425 strcpy (tempstr + 8, file); | |
1426 } | |
1427 else | |
1428 { | |
1429 len = strlen (file) + strlen (request->directory) + 21; | |
1430 tempstr = g_malloc (len + 1); | |
1431 strcpy (tempstr + 8, request->directory); | |
1432 strcat (tempstr + 8, "/"); | |
1433 strcat (tempstr + 8, file); | |
1434 } | |
1435 | |
1436 num = htonl (params->id++); | |
1437 memcpy (tempstr, &num, 4); | |
1438 | |
1439 num = htonl (len - 20); | |
1440 memcpy (tempstr + 4, &num, 4); | |
1441 | |
1442 num = htonl (SSH_FILEXFER_ATTR_ACMODTIME); | |
1443 memcpy (tempstr + len - 12, &num, 4); | |
1444 | |
1445 num = htonl (datetime); | |
1446 memcpy (tempstr + len - 8, &num, 4); | |
1447 | |
1448 num = htonl (datetime); | |
1449 memcpy (tempstr + len - 4, &num, 4); | |
1450 | |
1451 if (sshv2_send_command (request, SSH_FXP_SETSTAT, tempstr, len) < 0) | |
1452 { | |
1453 g_free (tempstr); | |
1454 return (-2); | |
1455 } | |
1456 g_free (tempstr); | |
1457 | |
1458 memset (&message, 0, sizeof (message)); | |
1459 if (sshv2_read_response (request, &message, NULL) < 0) | |
1460 return (-2); | |
1461 | |
1462 message.pos += 4; | |
1463 if (sshv2_buffer_get_int32 (request, &message, SSH_FX_OK) < 0) | |
1464 return (-2); | |
1465 | |
1466 sshv2_message_free (&message); | |
1467 | |
1468 return (0); | |
1469 } | |
1470 | |
1471 | |
1472 static off_t | |
1473 sshv2_get_file_size (gftp_request * request, const char *file) | |
1474 { | |
1475 gint32 len, highnum, lownum, attrs, num; | |
1476 sshv2_params * params; | |
1477 char *tempstr; | |
1478 #ifdef G_HAVE_GINT64 | |
1479 gint64 ret; | |
1480 #endif | |
1481 | |
1482 g_return_val_if_fail (request != NULL, -2); | |
1483 g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2); | |
1484 g_return_val_if_fail (file != NULL, -2); | |
1485 | |
1486 params = request->protocol_data; | |
1487 | |
1488 if (*file == '/') | |
1489 { | |
1490 len = strlen (file); | |
1491 tempstr = g_malloc (len + 9); | |
1492 strcpy (tempstr + 8, file); | |
1493 } | |
1494 else | |
1495 { | |
1496 len = strlen (file) + strlen (request->directory) + 1; | |
1497 tempstr = g_malloc (len + 9); | |
1498 strcpy (tempstr + 8, request->directory); | |
1499 strcat (tempstr + 8, "/"); | |
1500 strcat (tempstr + 8, file); | |
1501 } | |
1502 | |
1503 num = htonl (params->id++); | |
1504 memcpy (tempstr, &num, 4); | |
1505 | |
1506 num = htonl (len); | |
1507 memcpy (tempstr + 4, &num, 4); | |
1508 | |
1509 if (sshv2_send_command (request, SSH_FXP_STAT, tempstr, len + 8) < 0) | |
1510 { | |
1511 g_free (tempstr); | |
1512 return (-2); | |
1513 } | |
1514 g_free (tempstr); | |
1515 | |
1516 memset (¶ms->message, 0, sizeof (params->message)); | |
1517 if (sshv2_read_response (request, ¶ms->message, NULL) != SSH_FXP_ATTRS) | |
1518 { | |
1519 request->logging_function (gftp_logging_error, request->user_data, | |
1520 _("Received wrong response from server, disconnecting\n")); | |
1521 sshv2_message_free (¶ms->message); | |
1522 gftp_disconnect (request); | |
1523 return (-2); | |
1524 } | |
1525 | |
1526 if (params->message.length < 5) | |
1527 return (-2); | |
1528 params->message.pos += 4; | |
1529 | |
1530 if ((attrs = sshv2_buffer_get_int32 (request, ¶ms->message, -1)) < 0) | |
1531 return (-2); | |
1532 | |
1533 if (attrs & SSH_FILEXFER_ATTR_SIZE) | |
1534 { | |
1535 if ((highnum = sshv2_buffer_get_int32 (request, ¶ms->message, -1)) < 0) | |
1536 return (-2); | |
1537 | |
1538 if ((lownum = sshv2_buffer_get_int32 (request, ¶ms->message, -1)) < 0) | |
1539 return (-2); | |
1540 | |
1541 sshv2_message_free (¶ms->message); | |
1542 | |
1543 #if G_HAVE_GINT64 | |
1544 ret = (gint64) lownum | ((gint64) highnum >> 32); | |
1545 return (ret); | |
1546 #else | |
1547 return (lownum); | |
1548 #endif | |
1549 } | |
1550 | |
1551 sshv2_message_free (¶ms->message); | |
1552 | |
1553 return (0); | |
1554 | |
1555 } | |
1556 | |
1557 | |
1558 static long | |
1559 sshv2_get_file (gftp_request * request, const char *file, FILE * fd, | |
1560 off_t startsize) | |
1561 { | |
1562 sshv2_params * params; | |
1563 sshv2_message message; | |
1564 char *tempstr; | |
1565 size_t stlen; | |
1566 gint32 num; | |
1567 | |
1568 g_return_val_if_fail (request != NULL, -2); | |
1569 g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2); | |
1570 g_return_val_if_fail (request->sockfd != NULL, -2); | |
1571 /* fd ignored for this protocol */ | |
1572 | |
1573 params = request->protocol_data; | |
1574 params->offset = startsize; | |
1575 | |
1576 if (*file == '/') | |
1577 { | |
1578 stlen = strlen (file); | |
1579 tempstr = g_malloc (stlen + 16); | |
1580 strcpy (tempstr + 8, file); | |
1581 } | |
1582 else | |
1583 { | |
1584 stlen = strlen (file) + strlen (request->directory) + 1; | |
1585 tempstr = g_malloc (stlen + 16); | |
1586 strcpy (tempstr + 8, request->directory); | |
1587 strcat (tempstr + 8, "/"); | |
1588 strcat (tempstr + 8, file); | |
1589 } | |
1590 | |
1591 num = htonl (params->id++); | |
1592 memcpy (tempstr, &num, 4); | |
1593 | |
1594 num = htonl (stlen); | |
1595 memcpy (tempstr + 4, &num, 4); | |
1596 | |
1597 num = htonl (SSH_FXF_READ); | |
1598 memcpy (tempstr + 8 + stlen, &num, 4); | |
1599 | |
1600 memset (tempstr + 12 + stlen, 0, 4); | |
1601 | |
1602 if (sshv2_send_command (request, SSH_FXP_OPEN, tempstr, stlen + 16) < 0) | |
1603 { | |
1604 g_free (tempstr); | |
1605 return (-2); | |
1606 } | |
1607 | |
1608 g_free (tempstr); | |
1609 memset (&message, 0, sizeof (message)); | |
1610 if (sshv2_read_response (request, &message, NULL) != SSH_FXP_HANDLE) | |
1611 { | |
1612 request->logging_function (gftp_logging_error, request->user_data, | |
1613 _("Received wrong response from server, disconnecting\n")); | |
1614 sshv2_message_free (&message); | |
1615 gftp_disconnect (request); | |
1616 return (-2); | |
1617 } | |
1618 | |
1619 if (message.length - 4 > SSH_MAX_HANDLE_SIZE) | |
1620 { | |
1621 request->logging_function (gftp_logging_error, request->user_data, | |
1622 _("Error: Message size %d too big from server\n"), | |
1623 message.length - 4); | |
1624 sshv2_message_free (&message); | |
1625 gftp_disconnect (request); | |
1626 return (-1); | |
1627 | |
1628 } | |
1629 | |
1630 memset (params->handle, 0, 4); | |
1631 memcpy (params->handle + 4, message.buffer+ 4, message.length - 5); | |
1632 params->handle_len = message.length - 1; | |
1633 sshv2_message_free (&message); | |
1634 | |
1635 return (sshv2_get_file_size (request, file)); | |
1636 } | |
1637 | |
1638 | |
1639 static int | |
1640 sshv2_put_file (gftp_request * request, const char *file, FILE * fd, | |
1641 off_t startsize, off_t totalsize) | |
1642 { | |
1643 sshv2_params * params; | |
1644 sshv2_message message; | |
1645 char *tempstr; | |
1646 size_t stlen; | |
1647 gint32 num; | |
1648 | |
1649 g_return_val_if_fail (request != NULL, -2); | |
1650 g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2); | |
1651 g_return_val_if_fail (request->sockfd != NULL, -2); | |
1652 /* fd ignored for this protocol */ | |
1653 | |
1654 params = request->protocol_data; | |
1655 params->offset = 0; | |
1656 | |
1657 if (*file == '/') | |
1658 { | |
1659 stlen = strlen (file); | |
1660 tempstr = g_malloc (stlen + 16); | |
1661 strcpy (tempstr + 8, file); | |
1662 } | |
1663 else | |
1664 { | |
1665 stlen = strlen (file) + strlen (request->directory) + 1; | |
1666 tempstr = g_malloc (stlen + 16); | |
1667 strcpy (tempstr + 8, request->directory); | |
1668 strcat (tempstr + 8, "/"); | |
1669 strcat (tempstr + 8, file); | |
1670 } | |
1671 | |
1672 num = htonl (params->id++); | |
1673 memcpy (tempstr, &num, 4); | |
1674 | |
1675 num = htonl (stlen); | |
1676 memcpy (tempstr + 4, &num, 4); | |
1677 | |
1678 if (startsize > 0) | |
1679 num = htonl (SSH_FXF_WRITE | SSH_FXF_CREAT | SSH_FXF_APPEND); | |
1680 else | |
1681 num = htonl (SSH_FXF_WRITE | SSH_FXF_CREAT | SSH_FXF_TRUNC); | |
1682 memcpy (tempstr + 8 + stlen, &num, 4); | |
1683 | |
1684 memset (tempstr + 12 + stlen, 0, 4); | |
1685 | |
1686 if (sshv2_send_command (request, SSH_FXP_OPEN, tempstr, stlen + 16) < 0) | |
1687 { | |
1688 g_free (tempstr); | |
1689 return (-2); | |
1690 } | |
1691 | |
1692 g_free (tempstr); | |
1693 memset (&message, 0, sizeof (message)); | |
1694 if (sshv2_read_response (request, &message, NULL) != SSH_FXP_HANDLE) | |
1695 { | |
1696 request->logging_function (gftp_logging_error, request->user_data, | |
1697 _("Received wrong response from server, disconnecting\n")); | |
1698 sshv2_message_free (&message); | |
1699 gftp_disconnect (request); | |
1700 return (-2); | |
1701 } | |
1702 | |
1703 if (message.length - 4 > SSH_MAX_HANDLE_SIZE) | |
1704 { | |
1705 request->logging_function (gftp_logging_error, request->user_data, | |
1706 _("Error: Message size %d too big from server\n"), | |
1707 message.length - 4); | |
1708 sshv2_message_free (&message); | |
1709 gftp_disconnect (request); | |
1710 return (-1); | |
1711 | |
1712 } | |
1713 | |
1714 memset (params->handle, 0, 4); | |
1715 memcpy (params->handle + 4, message.buffer+ 4, message.length - 5); | |
1716 params->handle_len = message.length - 1; | |
1717 sshv2_message_free (&message); | |
1718 | |
1719 return (0); | |
1720 } | |
1721 | |
1722 | |
1723 static size_t | |
1724 sshv2_get_next_file_chunk (gftp_request * request, char *buf, size_t size) | |
1725 { | |
1726 sshv2_params * params; | |
1727 sshv2_message message; | |
1728 gint32 num; | |
1729 | |
1730 #ifdef G_HAVE_GINT64 | |
1731 gint64 offset; | |
1732 #else | |
1733 gint32 offset; | |
1734 #endif | |
1735 | |
1736 g_return_val_if_fail (request != NULL, -2); | |
1737 g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2); | |
1738 g_return_val_if_fail (request->sockfd != NULL, -2); | |
1739 g_return_val_if_fail (buf != NULL, -2); | |
1740 | |
1741 params = request->protocol_data; | |
1742 | |
1743 if (params->read_buffer == NULL) | |
1744 { | |
1745 params->read_buffer = g_malloc (params->handle_len + 12); | |
1746 num = htonl (params->handle_len); | |
1747 memcpy (params->read_buffer, params->handle, params->handle_len); | |
1748 } | |
1749 | |
1750 num = htonl (params->id++); | |
1751 memcpy (params->read_buffer, &num, 4); | |
1752 | |
1753 #ifdef G_HAVE_GINT64 | |
1754 offset = hton64 (params->offset); | |
1755 memcpy (params->read_buffer + params->handle_len, &offset, 8); | |
1756 #else | |
1757 memset (params->read_buffer + params->handle_len, 0, 4); | |
1758 offset = htonl (params->offset); | |
1759 memcpy (params->read_buffer + params->handle_len + 4, &offset, 4); | |
1760 #endif | |
1761 | |
1762 num = htonl (size); | |
1763 memcpy (params->read_buffer + params->handle_len + 8, &num, 4); | |
1764 | |
1765 if (sshv2_send_command (request, SSH_FXP_READ, params->read_buffer, params->handle_len + 12) < 0) | |
1766 return (-2); | |
1767 | |
1768 memset (&message, 0, sizeof (message)); | |
1769 if (sshv2_read_response (request, &message, NULL) != SSH_FXP_DATA) | |
1770 { | |
1771 message.pos += 4; | |
1772 if ((num = sshv2_buffer_get_int32 (request, &message, SSH_FX_OK)) < 0) | |
1773 return (-2); | |
1774 sshv2_message_free (&message); | |
1775 if (num != SSH_FX_EOF) | |
1776 { | |
1777 request->logging_function (gftp_logging_error, request->user_data, | |
1778 _("Received wrong response from server, disconnecting\n")); | |
1779 gftp_disconnect (request); | |
1780 return (-2); | |
1781 } | |
1782 return (0); | |
1783 } | |
1784 | |
1785 memcpy (&num, message.buffer + 4, 4); | |
1786 num = ntohl (num); | |
1787 if (num > size) | |
1788 { | |
1789 request->logging_function (gftp_logging_error, request->user_data, | |
1790 _("Error: Message size %d too big from server\n"), | |
1791 num); | |
1792 sshv2_message_free (&message); | |
1793 gftp_disconnect (request); | |
1794 return (-1); | |
1795 | |
1796 } | |
1797 | |
1798 memcpy (buf, message.buffer + 8, num); | |
1799 sshv2_message_free (&message); | |
1800 params->offset += num; | |
1801 return (num); | |
1802 } | |
1803 | |
1804 | |
1805 static size_t | |
1806 sshv2_put_next_file_chunk (gftp_request * request, char *buf, size_t size) | |
1807 { | |
1808 sshv2_params * params; | |
1809 sshv2_message message; | |
1810 char tempstr[32768]; | |
1811 gint32 num; | |
1812 int ret; | |
1813 | |
1814 #ifdef G_HAVE_GINT64 | |
1815 gint64 offset; | |
1816 #else | |
1817 gint32 offset; | |
1818 #endif | |
1819 | |
1820 g_return_val_if_fail (request != NULL, -2); | |
1821 g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, -2); | |
1822 g_return_val_if_fail (request->sockfd != NULL, -2); | |
1823 g_return_val_if_fail (buf != NULL, -2); | |
1824 g_return_val_if_fail (size <= 32500, -2); | |
1825 | |
1826 params = request->protocol_data; | |
1827 | |
1828 num = htonl (params->handle_len); | |
1829 memcpy (tempstr, params->handle, params->handle_len); | |
1830 | |
1831 num = htonl (params->id++); | |
1832 memcpy (tempstr, &num, 4); | |
1833 | |
1834 #ifdef G_HAVE_GINT64 | |
1835 offset = hton64 (params->offset); | |
1836 memcpy (tempstr + params->handle_len, &offset, 8); | |
1837 #else | |
1838 memset (tempstr + params->handle_len, 0, 4); | |
1839 offset = htonl (params->offset); | |
1840 memcpy (tempstr + params->handle_len + 4, &offset, 4); | |
1841 #endif | |
1842 | |
1843 num = htonl (size); | |
1844 memcpy (tempstr + params->handle_len + 8, &num, 4); | |
1845 memcpy (tempstr + params->handle_len + 12, buf, size); | |
1846 | |
1847 if (sshv2_send_command (request, SSH_FXP_WRITE, tempstr, params->handle_len + size + 12) < 0) | |
1848 { | |
1849 g_free (tempstr); | |
1850 return (-2); | |
1851 } | |
1852 | |
1853 memset (&message, 0, sizeof (message)); | |
1854 params->dont_log_status = 1; | |
1855 ret = sshv2_read_response (request, &message, NULL); | |
1856 params->dont_log_status = 0; | |
1857 if (ret != SSH_FXP_STATUS) | |
1858 { | |
1859 request->logging_function (gftp_logging_error, request->user_data, | |
1860 _("Received wrong response from server, disconnecting\n")); | |
1861 sshv2_message_free (&message); | |
1862 gftp_disconnect (request); | |
1863 return (-2); | |
1864 } | |
1865 | |
1866 message.pos += 4; | |
1867 if ((num = sshv2_buffer_get_int32 (request, &message, SSH_FX_OK)) < 0) | |
1868 return (-2); | |
1869 sshv2_message_free (&message); | |
1870 | |
1871 if (num == SSH_FX_EOF) | |
1872 return (0); | |
1873 else if (num != SSH_FX_OK) | |
1874 return (-1); | |
1875 | |
1876 params->offset += size; | |
1877 return (size); | |
1878 } | |
1879 | |
48 | 1880 |
1881 void | |
1882 sshv2_init (gftp_request * request) | |
1883 { | |
1884 sshv2_params * params; | |
1885 | |
1886 g_return_if_fail (request != NULL); | |
1887 | |
1888 request->protonum = GFTP_SSHV2_NUM; | |
1889 request->init = sshv2_init; | |
1890 request->destroy = sshv2_destroy; | |
1891 request->connect = sshv2_connect; | |
1892 request->disconnect = sshv2_disconnect; | |
1893 request->get_file = sshv2_get_file; | |
1894 request->put_file = sshv2_put_file; | |
1895 request->transfer_file = NULL; | |
1896 request->get_next_file_chunk = sshv2_get_next_file_chunk; | |
1897 request->put_next_file_chunk = sshv2_put_next_file_chunk; | |
1898 request->end_transfer = sshv2_end_transfer; | |
1899 request->abort_transfer = sshv2_end_transfer; /* NOTE: uses sshv2_end_transfer */ | |
1900 request->list_files = sshv2_list_files; | |
1901 request->get_next_file = sshv2_get_next_file; | |
1902 request->set_data_type = NULL; | |
1903 request->get_file_size = sshv2_get_file_size; | |
1904 request->chdir = sshv2_chdir; | |
1905 request->rmdir = sshv2_rmdir; | |
1906 request->rmfile = sshv2_rmfile; | |
1907 request->mkdir = sshv2_mkdir; | |
1908 request->rename = sshv2_rename; | |
1909 request->chmod = sshv2_chmod; | |
1910 request->set_file_time = sshv2_set_file_time; | |
1911 request->site = NULL; | |
1912 request->parse_url = NULL; | |
1913 request->url_prefix = "ssh2"; | |
1914 request->protocol_name = "SSH2"; | |
1915 request->need_hostport = 1; | |
1916 request->need_userpass = ssh_need_userpass; | |
1917 request->use_cache = 1; | |
1918 request->use_threads = 1; | |
1919 request->always_connected = 0; | |
1920 request->protocol_data = g_malloc0 (sizeof (sshv2_params)); | |
1921 gftp_set_config_options (request); | |
1922 | |
1923 params = request->protocol_data; | |
1924 params->id = 1; | |
1925 } | |
1926 |