summaryrefslogtreecommitdiff
path: root/sftp-client.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2002-02-13 14:10:32 +1100
committerDamien Miller <djm@mindrot.org>2002-02-13 14:10:32 +1100
commit3db5f530d0fdf8044d6014ab12940efe0bbecca7 (patch)
tree578c5ea0091f934c13d40264b033bbd2532d2e9a /sftp-client.c
parent3606ee29388781894e6374030d0e40fa46da4cf9 (diff)
- djm@cvs.openbsd.org 2002/02/13 00:59:23
[sftp-client.c sftp-client.h sftp-glob.c sftp-glob.h sftp.h] [sftp-int.c sftp-int.h] API cleanup and backwards compat for filexfer v.0 servers; ok markus@
Diffstat (limited to 'sftp-client.c')
-rw-r--r--sftp-client.c302
1 files changed, 176 insertions, 126 deletions
diff --git a/sftp-client.c b/sftp-client.c
index cb11fd581..481341c66 100644
--- a/sftp-client.c
+++ b/sftp-client.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2001-2002 Damien Miller. All rights reserved. 2 * Copyright (c) 2001,2002 Damien Miller. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
@@ -24,11 +24,11 @@
24 24
25/* XXX: memleaks */ 25/* XXX: memleaks */
26/* XXX: signed vs unsigned */ 26/* XXX: signed vs unsigned */
27/* XXX: we use fatal too much, error may be more appropriate in places */ 27/* XXX: remove all logging, only return status codes */
28/* XXX: copy between two remote sites */ 28/* XXX: copy between two remote sites */
29 29
30#include "includes.h" 30#include "includes.h"
31RCSID("$OpenBSD: sftp-client.c,v 1.22 2002/02/12 12:44:46 djm Exp $"); 31RCSID("$OpenBSD: sftp-client.c,v 1.23 2002/02/13 00:59:23 djm Exp $");
32 32
33#if defined(HAVE_SYS_QUEUE_H) && !defined(HAVE_BOGUS_SYS_QUEUE_H) 33#if defined(HAVE_SYS_QUEUE_H) && !defined(HAVE_BOGUS_SYS_QUEUE_H)
34#include <sys/queue.h> 34#include <sys/queue.h>
@@ -50,8 +50,14 @@ RCSID("$OpenBSD: sftp-client.c,v 1.22 2002/02/12 12:44:46 djm Exp $");
50/* Minimum amount of data to read at at time */ 50/* Minimum amount of data to read at at time */
51#define MIN_READ_SIZE 512 51#define MIN_READ_SIZE 512
52 52
53/* Message ID */ 53struct sftp_conn {
54static u_int msg_id = 1; 54 int fd_in;
55 int fd_out;
56 u_int transfer_buflen;
57 u_int num_requests;
58 u_int version;
59 u_int msg_id;
60};
55 61
56static void 62static void
57send_msg(int fd, Buffer *m) 63send_msg(int fd, Buffer *m)
@@ -219,11 +225,12 @@ get_decode_stat(int fd, u_int expected_id, int quiet)
219 return(a); 225 return(a);
220} 226}
221 227
222int 228struct sftp_conn *
223do_init(int fd_in, int fd_out) 229do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests)
224{ 230{
225 int type, version; 231 int type, version;
226 Buffer msg; 232 Buffer msg;
233 struct sftp_conn *ret;
227 234
228 buffer_init(&msg); 235 buffer_init(&msg);
229 buffer_put_char(&msg, SSH2_FXP_INIT); 236 buffer_put_char(&msg, SSH2_FXP_INIT);
@@ -239,7 +246,7 @@ do_init(int fd_in, int fd_out)
239 error("Invalid packet back from SSH2_FXP_INIT (type %d)", 246 error("Invalid packet back from SSH2_FXP_INIT (type %d)",
240 type); 247 type);
241 buffer_free(&msg); 248 buffer_free(&msg);
242 return(-1); 249 return(NULL);
243 } 250 }
244 version = buffer_get_int(&msg); 251 version = buffer_get_int(&msg);
245 252
@@ -257,25 +264,43 @@ do_init(int fd_in, int fd_out)
257 264
258 buffer_free(&msg); 265 buffer_free(&msg);
259 266
260 return(version); 267 ret = xmalloc(sizeof(*ret));
268 ret->fd_in = fd_in;
269 ret->fd_out = fd_out;
270 ret->transfer_buflen = transfer_buflen;
271 ret->num_requests = num_requests;
272 ret->version = version;
273 ret->msg_id = 1;
274
275 /* Some filexfer v.0 servers don't support large packets */
276 if (version == 0)
277 ret->transfer_buflen = MAX(ret->transfer_buflen, 20480);
278
279 return(ret);
280}
281
282u_int
283sftp_proto_version(struct sftp_conn *conn)
284{
285 return(conn->version);
261} 286}
262 287
263int 288int
264do_close(int fd_in, int fd_out, char *handle, u_int handle_len) 289do_close(struct sftp_conn *conn, char *handle, u_int handle_len)
265{ 290{
266 u_int id, status; 291 u_int id, status;
267 Buffer msg; 292 Buffer msg;
268 293
269 buffer_init(&msg); 294 buffer_init(&msg);
270 295
271 id = msg_id++; 296 id = conn->msg_id++;
272 buffer_put_char(&msg, SSH2_FXP_CLOSE); 297 buffer_put_char(&msg, SSH2_FXP_CLOSE);
273 buffer_put_int(&msg, id); 298 buffer_put_int(&msg, id);
274 buffer_put_string(&msg, handle, handle_len); 299 buffer_put_string(&msg, handle, handle_len);
275 send_msg(fd_out, &msg); 300 send_msg(conn->fd_out, &msg);
276 debug3("Sent message SSH2_FXP_CLOSE I:%d", id); 301 debug3("Sent message SSH2_FXP_CLOSE I:%d", id);
277 302
278 status = get_status(fd_in, id); 303 status = get_status(conn->fd_in, id);
279 if (status != SSH2_FX_OK) 304 if (status != SSH2_FX_OK)
280 error("Couldn't close file: %s", fx2txt(status)); 305 error("Couldn't close file: %s", fx2txt(status));
281 306
@@ -286,24 +311,24 @@ do_close(int fd_in, int fd_out, char *handle, u_int handle_len)
286 311
287 312
288static int 313static int
289do_lsreaddir(int fd_in, int fd_out, char *path, int printflag, 314do_lsreaddir(struct sftp_conn *conn, char *path, int printflag,
290 SFTP_DIRENT ***dir) 315 SFTP_DIRENT ***dir)
291{ 316{
292 Buffer msg; 317 Buffer msg;
293 u_int type, id, handle_len, i, expected_id, ents = 0; 318 u_int type, id, handle_len, i, expected_id, ents = 0;
294 char *handle; 319 char *handle;
295 320
296 id = msg_id++; 321 id = conn->msg_id++;
297 322
298 buffer_init(&msg); 323 buffer_init(&msg);
299 buffer_put_char(&msg, SSH2_FXP_OPENDIR); 324 buffer_put_char(&msg, SSH2_FXP_OPENDIR);
300 buffer_put_int(&msg, id); 325 buffer_put_int(&msg, id);
301 buffer_put_cstring(&msg, path); 326 buffer_put_cstring(&msg, path);
302 send_msg(fd_out, &msg); 327 send_msg(conn->fd_out, &msg);
303 328
304 buffer_clear(&msg); 329 buffer_clear(&msg);
305 330
306 handle = get_handle(fd_in, id, &handle_len); 331 handle = get_handle(conn->fd_in, id, &handle_len);
307 if (handle == NULL) 332 if (handle == NULL)
308 return(-1); 333 return(-1);
309 334
@@ -316,7 +341,7 @@ do_lsreaddir(int fd_in, int fd_out, char *path, int printflag,
316 for (;;) { 341 for (;;) {
317 int count; 342 int count;
318 343
319 id = expected_id = msg_id++; 344 id = expected_id = conn->msg_id++;
320 345
321 debug3("Sending SSH2_FXP_READDIR I:%d", id); 346 debug3("Sending SSH2_FXP_READDIR I:%d", id);
322 347
@@ -324,11 +349,11 @@ do_lsreaddir(int fd_in, int fd_out, char *path, int printflag,
324 buffer_put_char(&msg, SSH2_FXP_READDIR); 349 buffer_put_char(&msg, SSH2_FXP_READDIR);
325 buffer_put_int(&msg, id); 350 buffer_put_int(&msg, id);
326 buffer_put_string(&msg, handle, handle_len); 351 buffer_put_string(&msg, handle, handle_len);
327 send_msg(fd_out, &msg); 352 send_msg(conn->fd_out, &msg);
328 353
329 buffer_clear(&msg); 354 buffer_clear(&msg);
330 355
331 get_msg(fd_in, &msg); 356 get_msg(conn->fd_in, &msg);
332 357
333 type = buffer_get_char(&msg); 358 type = buffer_get_char(&msg);
334 id = buffer_get_int(&msg); 359 id = buffer_get_int(&msg);
@@ -348,7 +373,7 @@ do_lsreaddir(int fd_in, int fd_out, char *path, int printflag,
348 } else { 373 } else {
349 error("Couldn't read directory: %s", 374 error("Couldn't read directory: %s",
350 fx2txt(status)); 375 fx2txt(status));
351 do_close(fd_in, fd_out, handle, handle_len); 376 do_close(conn, handle, handle_len);
352 return(status); 377 return(status);
353 } 378 }
354 } else if (type != SSH2_FXP_NAME) 379 } else if (type != SSH2_FXP_NAME)
@@ -386,22 +411,22 @@ do_lsreaddir(int fd_in, int fd_out, char *path, int printflag,
386 } 411 }
387 412
388 buffer_free(&msg); 413 buffer_free(&msg);
389 do_close(fd_in, fd_out, handle, handle_len); 414 do_close(conn, handle, handle_len);
390 xfree(handle); 415 xfree(handle);
391 416
392 return(0); 417 return(0);
393} 418}
394 419
395int 420int
396do_ls(int fd_in, int fd_out, char *path) 421do_ls(struct sftp_conn *conn, char *path)
397{ 422{
398 return(do_lsreaddir(fd_in, fd_out, path, 1, NULL)); 423 return(do_lsreaddir(conn, path, 1, NULL));
399} 424}
400 425
401int 426int
402do_readdir(int fd_in, int fd_out, char *path, SFTP_DIRENT ***dir) 427do_readdir(struct sftp_conn *conn, char *path, SFTP_DIRENT ***dir)
403{ 428{
404 return(do_lsreaddir(fd_in, fd_out, path, 0, dir)); 429 return(do_lsreaddir(conn, path, 0, dir));
405} 430}
406 431
407void free_sftp_dirents(SFTP_DIRENT **s) 432void free_sftp_dirents(SFTP_DIRENT **s)
@@ -417,30 +442,31 @@ void free_sftp_dirents(SFTP_DIRENT **s)
417} 442}
418 443
419int 444int
420do_rm(int fd_in, int fd_out, char *path) 445do_rm(struct sftp_conn *conn, char *path)
421{ 446{
422 u_int status, id; 447 u_int status, id;
423 448
424 debug2("Sending SSH2_FXP_REMOVE \"%s\"", path); 449 debug2("Sending SSH2_FXP_REMOVE \"%s\"", path);
425 450
426 id = msg_id++; 451 id = conn->msg_id++;
427 send_string_request(fd_out, id, SSH2_FXP_REMOVE, path, strlen(path)); 452 send_string_request(conn->fd_out, id, SSH2_FXP_REMOVE, path,
428 status = get_status(fd_in, id); 453 strlen(path));
454 status = get_status(conn->fd_in, id);
429 if (status != SSH2_FX_OK) 455 if (status != SSH2_FX_OK)
430 error("Couldn't delete file: %s", fx2txt(status)); 456 error("Couldn't delete file: %s", fx2txt(status));
431 return(status); 457 return(status);
432} 458}
433 459
434int 460int
435do_mkdir(int fd_in, int fd_out, char *path, Attrib *a) 461do_mkdir(struct sftp_conn *conn, char *path, Attrib *a)
436{ 462{
437 u_int status, id; 463 u_int status, id;
438 464
439 id = msg_id++; 465 id = conn->msg_id++;
440 send_string_attrs_request(fd_out, id, SSH2_FXP_MKDIR, path, 466 send_string_attrs_request(conn->fd_out, id, SSH2_FXP_MKDIR, path,
441 strlen(path), a); 467 strlen(path), a);
442 468
443 status = get_status(fd_in, id); 469 status = get_status(conn->fd_in, id);
444 if (status != SSH2_FX_OK) 470 if (status != SSH2_FX_OK)
445 error("Couldn't create directory: %s", fx2txt(status)); 471 error("Couldn't create directory: %s", fx2txt(status));
446 472
@@ -448,14 +474,15 @@ do_mkdir(int fd_in, int fd_out, char *path, Attrib *a)
448} 474}
449 475
450int 476int
451do_rmdir(int fd_in, int fd_out, char *path) 477do_rmdir(struct sftp_conn *conn, char *path)
452{ 478{
453 u_int status, id; 479 u_int status, id;
454 480
455 id = msg_id++; 481 id = conn->msg_id++;
456 send_string_request(fd_out, id, SSH2_FXP_RMDIR, path, strlen(path)); 482 send_string_request(conn->fd_out, id, SSH2_FXP_RMDIR, path,
483 strlen(path));
457 484
458 status = get_status(fd_in, id); 485 status = get_status(conn->fd_in, id);
459 if (status != SSH2_FX_OK) 486 if (status != SSH2_FX_OK)
460 error("Couldn't remove directory: %s", fx2txt(status)); 487 error("Couldn't remove directory: %s", fx2txt(status));
461 488
@@ -463,45 +490,61 @@ do_rmdir(int fd_in, int fd_out, char *path)
463} 490}
464 491
465Attrib * 492Attrib *
466do_stat(int fd_in, int fd_out, char *path, int quiet) 493do_stat(struct sftp_conn *conn, char *path, int quiet)
467{ 494{
468 u_int id; 495 u_int id;
469 496
470 id = msg_id++; 497 id = conn->msg_id++;
471 send_string_request(fd_out, id, SSH2_FXP_STAT, path, strlen(path)); 498
472 return(get_decode_stat(fd_in, id, quiet)); 499 send_string_request(conn->fd_out, id,
500 conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT,
501 path, strlen(path));
502
503 return(get_decode_stat(conn->fd_in, id, quiet));
473} 504}
474 505
475Attrib * 506Attrib *
476do_lstat(int fd_in, int fd_out, char *path, int quiet) 507do_lstat(struct sftp_conn *conn, char *path, int quiet)
477{ 508{
478 u_int id; 509 u_int id;
479 510
480 id = msg_id++; 511 if (conn->version == 0) {
481 send_string_request(fd_out, id, SSH2_FXP_LSTAT, path, strlen(path)); 512 if (quiet)
482 return(get_decode_stat(fd_in, id, quiet)); 513 debug("Server version does not support lstat operation");
514 else
515 error("Server version does not support lstat operation");
516 return(NULL);
517 }
518
519 id = conn->msg_id++;
520 send_string_request(conn->fd_out, id, SSH2_FXP_LSTAT, path,
521 strlen(path));
522
523 return(get_decode_stat(conn->fd_in, id, quiet));
483} 524}
484 525
485Attrib * 526Attrib *
486do_fstat(int fd_in, int fd_out, char *handle, u_int handle_len, int quiet) 527do_fstat(struct sftp_conn *conn, char *handle, u_int handle_len, int quiet)
487{ 528{
488 u_int id; 529 u_int id;
489 530
490 id = msg_id++; 531 id = conn->msg_id++;
491 send_string_request(fd_out, id, SSH2_FXP_FSTAT, handle, handle_len); 532 send_string_request(conn->fd_out, id, SSH2_FXP_FSTAT, handle,
492 return(get_decode_stat(fd_in, id, quiet)); 533 handle_len);
534
535 return(get_decode_stat(conn->fd_in, id, quiet));
493} 536}
494 537
495int 538int
496do_setstat(int fd_in, int fd_out, char *path, Attrib *a) 539do_setstat(struct sftp_conn *conn, char *path, Attrib *a)
497{ 540{
498 u_int status, id; 541 u_int status, id;
499 542
500 id = msg_id++; 543 id = conn->msg_id++;
501 send_string_attrs_request(fd_out, id, SSH2_FXP_SETSTAT, path, 544 send_string_attrs_request(conn->fd_out, id, SSH2_FXP_SETSTAT, path,
502 strlen(path), a); 545 strlen(path), a);
503 546
504 status = get_status(fd_in, id); 547 status = get_status(conn->fd_in, id);
505 if (status != SSH2_FX_OK) 548 if (status != SSH2_FX_OK)
506 error("Couldn't setstat on \"%s\": %s", path, 549 error("Couldn't setstat on \"%s\": %s", path,
507 fx2txt(status)); 550 fx2txt(status));
@@ -510,16 +553,16 @@ do_setstat(int fd_in, int fd_out, char *path, Attrib *a)
510} 553}
511 554
512int 555int
513do_fsetstat(int fd_in, int fd_out, char *handle, u_int handle_len, 556do_fsetstat(struct sftp_conn *conn, char *handle, u_int handle_len,
514 Attrib *a) 557 Attrib *a)
515{ 558{
516 u_int status, id; 559 u_int status, id;
517 560
518 id = msg_id++; 561 id = conn->msg_id++;
519 send_string_attrs_request(fd_out, id, SSH2_FXP_FSETSTAT, handle, 562 send_string_attrs_request(conn->fd_out, id, SSH2_FXP_FSETSTAT, handle,
520 handle_len, a); 563 handle_len, a);
521 564
522 status = get_status(fd_in, id); 565 status = get_status(conn->fd_in, id);
523 if (status != SSH2_FX_OK) 566 if (status != SSH2_FX_OK)
524 error("Couldn't fsetstat: %s", fx2txt(status)); 567 error("Couldn't fsetstat: %s", fx2txt(status));
525 568
@@ -527,19 +570,20 @@ do_fsetstat(int fd_in, int fd_out, char *handle, u_int handle_len,
527} 570}
528 571
529char * 572char *
530do_realpath(int fd_in, int fd_out, char *path) 573do_realpath(struct sftp_conn *conn, char *path)
531{ 574{
532 Buffer msg; 575 Buffer msg;
533 u_int type, expected_id, count, id; 576 u_int type, expected_id, count, id;
534 char *filename, *longname; 577 char *filename, *longname;
535 Attrib *a; 578 Attrib *a;
536 579
537 expected_id = id = msg_id++; 580 expected_id = id = conn->msg_id++;
538 send_string_request(fd_out, id, SSH2_FXP_REALPATH, path, strlen(path)); 581 send_string_request(conn->fd_out, id, SSH2_FXP_REALPATH, path,
582 strlen(path));
539 583
540 buffer_init(&msg); 584 buffer_init(&msg);
541 585
542 get_msg(fd_in, &msg); 586 get_msg(conn->fd_in, &msg);
543 type = buffer_get_char(&msg); 587 type = buffer_get_char(&msg);
544 id = buffer_get_int(&msg); 588 id = buffer_get_int(&msg);
545 589
@@ -573,7 +617,7 @@ do_realpath(int fd_in, int fd_out, char *path)
573} 617}
574 618
575int 619int
576do_rename(int fd_in, int fd_out, char *oldpath, char *newpath) 620do_rename(struct sftp_conn *conn, char *oldpath, char *newpath)
577{ 621{
578 Buffer msg; 622 Buffer msg;
579 u_int status, id; 623 u_int status, id;
@@ -581,65 +625,71 @@ do_rename(int fd_in, int fd_out, char *oldpath, char *newpath)
581 buffer_init(&msg); 625 buffer_init(&msg);
582 626
583 /* Send rename request */ 627 /* Send rename request */
584 id = msg_id++; 628 id = conn->msg_id++;
585 buffer_put_char(&msg, SSH2_FXP_RENAME); 629 buffer_put_char(&msg, SSH2_FXP_RENAME);
586 buffer_put_int(&msg, id); 630 buffer_put_int(&msg, id);
587 buffer_put_cstring(&msg, oldpath); 631 buffer_put_cstring(&msg, oldpath);
588 buffer_put_cstring(&msg, newpath); 632 buffer_put_cstring(&msg, newpath);
589 send_msg(fd_out, &msg); 633 send_msg(conn->fd_out, &msg);
590 debug3("Sent message SSH2_FXP_RENAME \"%s\" -> \"%s\"", oldpath, 634 debug3("Sent message SSH2_FXP_RENAME \"%s\" -> \"%s\"", oldpath,
591 newpath); 635 newpath);
592 buffer_free(&msg); 636 buffer_free(&msg);
593 637
594 status = get_status(fd_in, id); 638 status = get_status(conn->fd_in, id);
595 if (status != SSH2_FX_OK) 639 if (status != SSH2_FX_OK)
596 error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath, newpath, 640 error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath,
597 fx2txt(status)); 641 newpath, fx2txt(status));
598 642
599 return(status); 643 return(status);
600} 644}
601 645
602int 646int
603do_symlink(int fd_in, int fd_out, char *oldpath, char *newpath) 647do_symlink(struct sftp_conn *conn, char *oldpath, char *newpath)
604{ 648{
605 Buffer msg; 649 Buffer msg;
606 u_int status, id; 650 u_int status, id;
607 651
652 if (conn->version < 3) {
653 error("This server does not support the symlink operation");
654 return(SSH2_FX_OP_UNSUPPORTED);
655 }
656
608 buffer_init(&msg); 657 buffer_init(&msg);
609 658
610 /* Send rename request */ 659 /* Send rename request */
611 id = msg_id++; 660 id = conn->msg_id++;
612 buffer_put_char(&msg, SSH2_FXP_SYMLINK); 661 buffer_put_char(&msg, SSH2_FXP_SYMLINK);
613 buffer_put_int(&msg, id); 662 buffer_put_int(&msg, id);
614 buffer_put_cstring(&msg, oldpath); 663 buffer_put_cstring(&msg, oldpath);
615 buffer_put_cstring(&msg, newpath); 664 buffer_put_cstring(&msg, newpath);
616 send_msg(fd_out, &msg); 665 send_msg(conn->fd_out, &msg);
617 debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath, 666 debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath,
618 newpath); 667 newpath);
619 buffer_free(&msg); 668 buffer_free(&msg);
620 669
621 status = get_status(fd_in, id); 670 status = get_status(conn->fd_in, id);
622 if (status != SSH2_FX_OK) 671 if (status != SSH2_FX_OK)
623 error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath, newpath, 672 error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath,
624 fx2txt(status)); 673 newpath, fx2txt(status));
625 674
626 return(status); 675 return(status);
627} 676}
628 677
629char * 678char *
630do_readlink(int fd_in, int fd_out, char *path) 679do_readlink(struct sftp_conn *conn, char *path)
631{ 680{
632 Buffer msg; 681 Buffer msg;
633 u_int type, expected_id, count, id; 682 u_int type, expected_id, count, id;
634 char *filename, *longname; 683 char *filename, *longname;
635 Attrib *a; 684 Attrib *a;
636 685
637 expected_id = id = msg_id++; 686 expected_id = id = conn->msg_id++;
638 send_string_request(fd_out, id, SSH2_FXP_READLINK, path, strlen(path)); 687 send_string_request(conn->fd_out, id, SSH2_FXP_READLINK, path,
688 strlen(path));
639 689
640 buffer_init(&msg); 690 buffer_init(&msg);
641 691
642 get_msg(fd_in, &msg); 692 get_msg(conn->fd_in, &msg);
643 type = buffer_get_char(&msg); 693 type = buffer_get_char(&msg);
644 id = buffer_get_int(&msg); 694 id = buffer_get_int(&msg);
645 695
@@ -690,8 +740,8 @@ send_read_request(int fd_out, u_int id, u_int64_t offset, u_int len,
690} 740}
691 741
692int 742int
693do_download(int fd_in, int fd_out, char *remote_path, char *local_path, 743do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
694 int pflag, size_t buflen, int num_requests) 744 int pflag)
695{ 745{
696 Attrib junk, *a; 746 Attrib junk, *a;
697 Buffer msg; 747 Buffer msg;
@@ -699,7 +749,7 @@ do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
699 int local_fd, status, num_req, max_req, write_error; 749 int local_fd, status, num_req, max_req, write_error;
700 int read_error, write_errno; 750 int read_error, write_errno;
701 u_int64_t offset, size; 751 u_int64_t offset, size;
702 u_int handle_len, mode, type, id; 752 u_int handle_len, mode, type, id, buflen;
703 struct request { 753 struct request {
704 u_int id; 754 u_int id;
705 u_int len; 755 u_int len;
@@ -711,7 +761,7 @@ do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
711 761
712 TAILQ_INIT(&requests); 762 TAILQ_INIT(&requests);
713 763
714 a = do_stat(fd_in, fd_out, remote_path, 0); 764 a = do_stat(conn, remote_path, 0);
715 if (a == NULL) 765 if (a == NULL)
716 return(-1); 766 return(-1);
717 767
@@ -732,33 +782,34 @@ do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
732 else 782 else
733 size = 0; 783 size = 0;
734 784
735 local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC, mode); 785 buflen = conn->transfer_buflen;
736 if (local_fd == -1) {
737 error("Couldn't open local file \"%s\" for writing: %s",
738 local_path, strerror(errno));
739 return(-1);
740 }
741
742 buffer_init(&msg); 786 buffer_init(&msg);
743 787
744 /* Send open request */ 788 /* Send open request */
745 id = msg_id++; 789 id = conn->msg_id++;
746 buffer_put_char(&msg, SSH2_FXP_OPEN); 790 buffer_put_char(&msg, SSH2_FXP_OPEN);
747 buffer_put_int(&msg, id); 791 buffer_put_int(&msg, id);
748 buffer_put_cstring(&msg, remote_path); 792 buffer_put_cstring(&msg, remote_path);
749 buffer_put_int(&msg, SSH2_FXF_READ); 793 buffer_put_int(&msg, SSH2_FXF_READ);
750 attrib_clear(&junk); /* Send empty attributes */ 794 attrib_clear(&junk); /* Send empty attributes */
751 encode_attrib(&msg, &junk); 795 encode_attrib(&msg, &junk);
752 send_msg(fd_out, &msg); 796 send_msg(conn->fd_out, &msg);
753 debug3("Sent message SSH2_FXP_OPEN I:%d P:%s", id, remote_path); 797 debug3("Sent message SSH2_FXP_OPEN I:%d P:%s", id, remote_path);
754 798
755 handle = get_handle(fd_in, id, &handle_len); 799 handle = get_handle(conn->fd_in, id, &handle_len);
756 if (handle == NULL) { 800 if (handle == NULL) {
757 buffer_free(&msg); 801 buffer_free(&msg);
758 close(local_fd); 802 close(local_fd);
759 return(-1); 803 return(-1);
760 } 804 }
761 805
806 local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC, mode);
807 if (local_fd == -1) {
808 error("Couldn't open local file \"%s\" for writing: %s",
809 local_path, strerror(errno));
810 return(-1);
811 }
812
762 /* Read from remote and write to local */ 813 /* Read from remote and write to local */
763 write_error = read_error = write_errno = num_req = offset = 0; 814 write_error = read_error = write_errno = num_req = offset = 0;
764 max_req = 1; 815 max_req = 1;
@@ -771,18 +822,18 @@ do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
771 debug3("Request range %llu -> %llu (%d/%d)", 822 debug3("Request range %llu -> %llu (%d/%d)",
772 offset, offset + buflen - 1, num_req, max_req); 823 offset, offset + buflen - 1, num_req, max_req);
773 req = xmalloc(sizeof(*req)); 824 req = xmalloc(sizeof(*req));
774 req->id = msg_id++; 825 req->id = conn->msg_id++;
775 req->len = buflen; 826 req->len = buflen;
776 req->offset = offset; 827 req->offset = offset;
777 offset += buflen; 828 offset += buflen;
778 num_req++; 829 num_req++;
779 TAILQ_INSERT_TAIL(&requests, req, tq); 830 TAILQ_INSERT_TAIL(&requests, req, tq);
780 send_read_request(fd_out, req->id, req->offset, 831 send_read_request(conn->fd_out, req->id, req->offset,
781 req->len, handle, handle_len); 832 req->len, handle, handle_len);
782 } 833 }
783 834
784 buffer_clear(&msg); 835 buffer_clear(&msg);
785 get_msg(fd_in, &msg); 836 get_msg(conn->fd_in, &msg);
786 type = buffer_get_char(&msg); 837 type = buffer_get_char(&msg);
787 id = buffer_get_int(&msg); 838 id = buffer_get_int(&msg);
788 debug3("Received reply T:%d I:%d R:%d", type, id, max_req); 839 debug3("Received reply T:%d I:%d R:%d", type, id, max_req);
@@ -830,12 +881,11 @@ do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
830 debug3("Short data block, re-requesting " 881 debug3("Short data block, re-requesting "
831 "%llu -> %llu (%2d)", req->offset + len, 882 "%llu -> %llu (%2d)", req->offset + len,
832 req->offset + req->len - 1, num_req); 883 req->offset + req->len - 1, num_req);
833 req->id = msg_id++; 884 req->id = conn->msg_id++;
834 req->len -= len; 885 req->len -= len;
835 req->offset += len; 886 req->offset += len;
836 send_read_request(fd_out, req->id, 887 send_read_request(conn->fd_out, req->id,
837 req->offset, req->len, handle, 888 req->offset, req->len, handle, handle_len);
838 handle_len);
839 /* Reduce the request size */ 889 /* Reduce the request size */
840 if (len < buflen) 890 if (len < buflen)
841 buflen = MAX(MIN_READ_SIZE, len); 891 buflen = MAX(MIN_READ_SIZE, len);
@@ -848,7 +898,7 @@ do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
848 offset, num_req); 898 offset, num_req);
849 max_req = 1; 899 max_req = 1;
850 } 900 }
851 else if (max_req < num_requests + 1) { 901 else if (max_req < conn->num_requests + 1) {
852 ++max_req; 902 ++max_req;
853 } 903 }
854 } 904 }
@@ -864,17 +914,16 @@ do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
864 fatal("Transfer complete, but requests still in queue"); 914 fatal("Transfer complete, but requests still in queue");
865 915
866 if (read_error) { 916 if (read_error) {
867 error("Couldn't read from remote " 917 error("Couldn't read from remote file \"%s\" : %s",
868 "file \"%s\" : %s", remote_path, 918 remote_path, fx2txt(status));
869 fx2txt(status)); 919 do_close(conn, handle, handle_len);
870 do_close(fd_in, fd_out, handle, handle_len);
871 } else if (write_error) { 920 } else if (write_error) {
872 error("Couldn't write to \"%s\": %s", local_path, 921 error("Couldn't write to \"%s\": %s", local_path,
873 strerror(write_errno)); 922 strerror(write_errno));
874 status = -1; 923 status = -1;
875 do_close(fd_in, fd_out, handle, handle_len); 924 do_close(conn, handle, handle_len);
876 } else { 925 } else {
877 status = do_close(fd_in, fd_out, handle, handle_len); 926 status = do_close(conn, handle, handle_len);
878 927
879 /* Override umask and utimes if asked */ 928 /* Override umask and utimes if asked */
880#ifdef HAVE_FCHMOD 929#ifdef HAVE_FCHMOD
@@ -897,12 +946,13 @@ do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
897 close(local_fd); 946 close(local_fd);
898 buffer_free(&msg); 947 buffer_free(&msg);
899 xfree(handle); 948 xfree(handle);
900 return status; 949
950 return(status);
901} 951}
902 952
903int 953int
904do_upload(int fd_in, int fd_out, char *local_path, char *remote_path, 954do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
905 int pflag, size_t buflen, int num_requests) 955 int pflag)
906{ 956{
907 int local_fd, status; 957 int local_fd, status;
908 u_int handle_len, id, type; 958 u_int handle_len, id, type;
@@ -946,18 +996,18 @@ do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
946 buffer_init(&msg); 996 buffer_init(&msg);
947 997
948 /* Send open request */ 998 /* Send open request */
949 id = msg_id++; 999 id = conn->msg_id++;
950 buffer_put_char(&msg, SSH2_FXP_OPEN); 1000 buffer_put_char(&msg, SSH2_FXP_OPEN);
951 buffer_put_int(&msg, id); 1001 buffer_put_int(&msg, id);
952 buffer_put_cstring(&msg, remote_path); 1002 buffer_put_cstring(&msg, remote_path);
953 buffer_put_int(&msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC); 1003 buffer_put_int(&msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC);
954 encode_attrib(&msg, &a); 1004 encode_attrib(&msg, &a);
955 send_msg(fd_out, &msg); 1005 send_msg(conn->fd_out, &msg);
956 debug3("Sent message SSH2_FXP_OPEN I:%d P:%s", id, remote_path); 1006 debug3("Sent message SSH2_FXP_OPEN I:%d P:%s", id, remote_path);
957 1007
958 buffer_clear(&msg); 1008 buffer_clear(&msg);
959 1009
960 handle = get_handle(fd_in, id, &handle_len); 1010 handle = get_handle(conn->fd_in, id, &handle_len);
961 if (handle == NULL) { 1011 if (handle == NULL) {
962 close(local_fd); 1012 close(local_fd);
963 buffer_free(&msg); 1013 buffer_free(&msg);
@@ -965,7 +1015,7 @@ do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
965 } 1015 }
966 1016
967 startid = ackid = id + 1; 1017 startid = ackid = id + 1;
968 data = xmalloc(buflen); 1018 data = xmalloc(conn->transfer_buflen);
969 1019
970 /* Read from local and write to remote */ 1020 /* Read from local and write to remote */
971 offset = 0; 1021 offset = 0;
@@ -977,7 +1027,7 @@ do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
977 * the last block of the file 1027 * the last block of the file
978 */ 1028 */
979 do 1029 do
980 len = read(local_fd, data, buflen); 1030 len = read(local_fd, data, conn->transfer_buflen);
981 while ((len == -1) && (errno == EINTR || errno == EAGAIN)); 1031 while ((len == -1) && (errno == EINTR || errno == EAGAIN));
982 1032
983 if (len == -1) 1033 if (len == -1)
@@ -997,7 +1047,7 @@ do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
997 buffer_put_string(&msg, handle, handle_len); 1047 buffer_put_string(&msg, handle, handle_len);
998 buffer_put_int64(&msg, offset); 1048 buffer_put_int64(&msg, offset);
999 buffer_put_string(&msg, data, len); 1049 buffer_put_string(&msg, data, len);
1000 send_msg(fd_out, &msg); 1050 send_msg(conn->fd_out, &msg);
1001 debug3("Sent message SSH2_FXP_WRITE I:%d O:%llu S:%u", 1051 debug3("Sent message SSH2_FXP_WRITE I:%d O:%llu S:%u",
1002 id, (u_int64_t)offset, len); 1052 id, (u_int64_t)offset, len);
1003 } else if (TAILQ_FIRST(&acks) == NULL) 1053 } else if (TAILQ_FIRST(&acks) == NULL)
@@ -1006,9 +1056,10 @@ do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
1006 if (ack == NULL) 1056 if (ack == NULL)
1007 fatal("Unexpected ACK %u", id); 1057 fatal("Unexpected ACK %u", id);
1008 1058
1009 if (id == startid || len == 0 || id - ackid >= num_requests) { 1059 if (id == startid || len == 0 ||
1060 id - ackid >= conn->num_requests) {
1010 buffer_clear(&msg); 1061 buffer_clear(&msg);
1011 get_msg(fd_in, &msg); 1062 get_msg(conn->fd_in, &msg);
1012 type = buffer_get_char(&msg); 1063 type = buffer_get_char(&msg);
1013 id = buffer_get_int(&msg); 1064 id = buffer_get_int(&msg);
1014 1065
@@ -1031,7 +1082,7 @@ do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
1031 if (status != SSH2_FX_OK) { 1082 if (status != SSH2_FX_OK) {
1032 error("Couldn't write to remote file \"%s\": %s", 1083 error("Couldn't write to remote file \"%s\": %s",
1033 remote_path, fx2txt(status)); 1084 remote_path, fx2txt(status));
1034 do_close(fd_in, fd_out, handle, handle_len); 1085 do_close(conn, handle, handle_len);
1035 close(local_fd); 1086 close(local_fd);
1036 goto done; 1087 goto done;
1037 } 1088 }
@@ -1040,7 +1091,6 @@ do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
1040 ++ackid; 1091 ++ackid;
1041 free(ack); 1092 free(ack);
1042 } 1093 }
1043
1044 offset += len; 1094 offset += len;
1045 } 1095 }
1046 xfree(data); 1096 xfree(data);
@@ -1048,19 +1098,19 @@ do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
1048 if (close(local_fd) == -1) { 1098 if (close(local_fd) == -1) {
1049 error("Couldn't close local file \"%s\": %s", local_path, 1099 error("Couldn't close local file \"%s\": %s", local_path,
1050 strerror(errno)); 1100 strerror(errno));
1051 do_close(fd_in, fd_out, handle, handle_len); 1101 do_close(conn, handle, handle_len);
1052 status = -1; 1102 status = -1;
1053 goto done; 1103 goto done;
1054 } 1104 }
1055 1105
1056 /* Override umask and utimes if asked */ 1106 /* Override umask and utimes if asked */
1057 if (pflag) 1107 if (pflag)
1058 do_fsetstat(fd_in, fd_out, handle, handle_len, &a); 1108 do_fsetstat(conn, handle, handle_len, &a);
1059 1109
1060 status = do_close(fd_in, fd_out, handle, handle_len); 1110 status = do_close(conn, handle, handle_len);
1061 1111
1062done: 1112done:
1063 xfree(handle); 1113 xfree(handle);
1064 buffer_free(&msg); 1114 buffer_free(&msg);
1065 return status; 1115 return(status);
1066} 1116}