diff options
Diffstat (limited to 'sftp-int.c')
-rw-r--r-- | sftp-int.c | 104 |
1 files changed, 46 insertions, 58 deletions
diff --git a/sftp-int.c b/sftp-int.c index babc0ed60..5de93891a 100644 --- a/sftp-int.c +++ b/sftp-int.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2001 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 |
@@ -26,7 +26,7 @@ | |||
26 | /* XXX: recursive operations */ | 26 | /* XXX: recursive operations */ |
27 | 27 | ||
28 | #include "includes.h" | 28 | #include "includes.h" |
29 | RCSID("$OpenBSD: sftp-int.c,v 1.43 2002/02/12 12:32:27 djm Exp $"); | 29 | RCSID("$OpenBSD: sftp-int.c,v 1.44 2002/02/13 00:59:23 djm Exp $"); |
30 | 30 | ||
31 | #include "buffer.h" | 31 | #include "buffer.h" |
32 | #include "xmalloc.h" | 32 | #include "xmalloc.h" |
@@ -48,9 +48,6 @@ extern size_t copy_buffer_len; | |||
48 | /* Number of concurrent outstanding requests */ | 48 | /* Number of concurrent outstanding requests */ |
49 | extern int num_requests; | 49 | extern int num_requests; |
50 | 50 | ||
51 | /* Version of server we are speaking to */ | ||
52 | int version; | ||
53 | |||
54 | /* Seperators for interactive commands */ | 51 | /* Seperators for interactive commands */ |
55 | #define WHITESPACE " \t\r\n" | 52 | #define WHITESPACE " \t\r\n" |
56 | 53 | ||
@@ -336,12 +333,12 @@ is_dir(char *path) | |||
336 | } | 333 | } |
337 | 334 | ||
338 | static int | 335 | static int |
339 | remote_is_dir(int in, int out, char *path) | 336 | remote_is_dir(struct sftp_conn *conn, char *path) |
340 | { | 337 | { |
341 | Attrib *a; | 338 | Attrib *a; |
342 | 339 | ||
343 | /* XXX: report errors? */ | 340 | /* XXX: report errors? */ |
344 | if ((a = do_stat(in, out, path, 1)) == NULL) | 341 | if ((a = do_stat(conn, path, 1)) == NULL) |
345 | return(0); | 342 | return(0); |
346 | if (!(a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) | 343 | if (!(a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) |
347 | return(0); | 344 | return(0); |
@@ -349,7 +346,7 @@ remote_is_dir(int in, int out, char *path) | |||
349 | } | 346 | } |
350 | 347 | ||
351 | static int | 348 | static int |
352 | process_get(int in, int out, char *src, char *dst, char *pwd, int pflag) | 349 | process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag) |
353 | { | 350 | { |
354 | char *abs_src = NULL; | 351 | char *abs_src = NULL; |
355 | char *abs_dst = NULL; | 352 | char *abs_dst = NULL; |
@@ -363,7 +360,7 @@ process_get(int in, int out, char *src, char *dst, char *pwd, int pflag) | |||
363 | 360 | ||
364 | memset(&g, 0, sizeof(g)); | 361 | memset(&g, 0, sizeof(g)); |
365 | debug3("Looking up %s", abs_src); | 362 | debug3("Looking up %s", abs_src); |
366 | if (remote_glob(in, out, abs_src, 0, NULL, &g)) { | 363 | if (remote_glob(conn, abs_src, 0, NULL, &g)) { |
367 | error("File \"%s\" not found.", abs_src); | 364 | error("File \"%s\" not found.", abs_src); |
368 | err = -1; | 365 | err = -1; |
369 | goto out; | 366 | goto out; |
@@ -387,8 +384,7 @@ process_get(int in, int out, char *src, char *dst, char *pwd, int pflag) | |||
387 | goto out; | 384 | goto out; |
388 | } | 385 | } |
389 | printf("Fetching %s to %s\n", g.gl_pathv[0], abs_dst); | 386 | printf("Fetching %s to %s\n", g.gl_pathv[0], abs_dst); |
390 | err = do_download(in, out, g.gl_pathv[0], abs_dst, pflag, | 387 | err = do_download(conn, g.gl_pathv[0], abs_dst, pflag); |
391 | copy_buffer_len, num_requests); | ||
392 | goto out; | 388 | goto out; |
393 | } | 389 | } |
394 | 390 | ||
@@ -412,8 +408,7 @@ process_get(int in, int out, char *src, char *dst, char *pwd, int pflag) | |||
412 | abs_dst = tmp; | 408 | abs_dst = tmp; |
413 | 409 | ||
414 | printf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst); | 410 | printf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst); |
415 | if (do_download(in, out, g.gl_pathv[i], abs_dst, pflag, | 411 | if (do_download(conn, g.gl_pathv[i], abs_dst, pflag) == -1) |
416 | copy_buffer_len, num_requests) == -1) | ||
417 | err = -1; | 412 | err = -1; |
418 | xfree(abs_dst); | 413 | xfree(abs_dst); |
419 | abs_dst = NULL; | 414 | abs_dst = NULL; |
@@ -428,7 +423,7 @@ out: | |||
428 | } | 423 | } |
429 | 424 | ||
430 | static int | 425 | static int |
431 | process_put(int in, int out, char *src, char *dst, char *pwd, int pflag) | 426 | process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag) |
432 | { | 427 | { |
433 | char *tmp_dst = NULL; | 428 | char *tmp_dst = NULL; |
434 | char *abs_dst = NULL; | 429 | char *abs_dst = NULL; |
@@ -454,7 +449,7 @@ process_put(int in, int out, char *src, char *dst, char *pwd, int pflag) | |||
454 | if (g.gl_pathv[0] && g.gl_matchc == 1) { | 449 | if (g.gl_pathv[0] && g.gl_matchc == 1) { |
455 | if (tmp_dst) { | 450 | if (tmp_dst) { |
456 | /* If directory specified, append filename */ | 451 | /* If directory specified, append filename */ |
457 | if (remote_is_dir(in, out, tmp_dst)) { | 452 | if (remote_is_dir(conn, tmp_dst)) { |
458 | if (infer_path(g.gl_pathv[0], &tmp)) { | 453 | if (infer_path(g.gl_pathv[0], &tmp)) { |
459 | err = 1; | 454 | err = 1; |
460 | goto out; | 455 | goto out; |
@@ -471,13 +466,12 @@ process_put(int in, int out, char *src, char *dst, char *pwd, int pflag) | |||
471 | abs_dst = make_absolute(abs_dst, pwd); | 466 | abs_dst = make_absolute(abs_dst, pwd); |
472 | } | 467 | } |
473 | printf("Uploading %s to %s\n", g.gl_pathv[0], abs_dst); | 468 | printf("Uploading %s to %s\n", g.gl_pathv[0], abs_dst); |
474 | err = do_upload(in, out, g.gl_pathv[0], abs_dst, pflag, | 469 | err = do_upload(conn, g.gl_pathv[0], abs_dst, pflag); |
475 | copy_buffer_len, num_requests); | ||
476 | goto out; | 470 | goto out; |
477 | } | 471 | } |
478 | 472 | ||
479 | /* Multiple matches, dst may be directory or unspecified */ | 473 | /* Multiple matches, dst may be directory or unspecified */ |
480 | if (tmp_dst && !remote_is_dir(in, out, tmp_dst)) { | 474 | if (tmp_dst && !remote_is_dir(conn, tmp_dst)) { |
481 | error("Multiple files match, but \"%s\" is not a directory", | 475 | error("Multiple files match, but \"%s\" is not a directory", |
482 | tmp_dst); | 476 | tmp_dst); |
483 | err = -1; | 477 | err = -1; |
@@ -496,8 +490,7 @@ process_put(int in, int out, char *src, char *dst, char *pwd, int pflag) | |||
496 | abs_dst = make_absolute(tmp, pwd); | 490 | abs_dst = make_absolute(tmp, pwd); |
497 | 491 | ||
498 | printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst); | 492 | printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst); |
499 | if (do_upload(in, out, g.gl_pathv[i], abs_dst, pflag, | 493 | if (do_upload(conn, g.gl_pathv[i], abs_dst, pflag) == -1) |
500 | copy_buffer_len, num_requests) == -1) | ||
501 | err = -1; | 494 | err = -1; |
502 | } | 495 | } |
503 | 496 | ||
@@ -655,7 +648,7 @@ parse_args(const char **cpp, int *pflag, unsigned long *n_arg, | |||
655 | } | 648 | } |
656 | 649 | ||
657 | static int | 650 | static int |
658 | parse_dispatch_command(int in, int out, const char *cmd, char **pwd) | 651 | parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd) |
659 | { | 652 | { |
660 | char *path1, *path2, *tmp; | 653 | char *path1, *path2, *tmp; |
661 | int pflag, cmdnum, i; | 654 | int pflag, cmdnum, i; |
@@ -675,32 +668,26 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd) | |||
675 | case -1: | 668 | case -1: |
676 | break; | 669 | break; |
677 | case I_GET: | 670 | case I_GET: |
678 | err = process_get(in, out, path1, path2, *pwd, pflag); | 671 | err = process_get(conn, path1, path2, *pwd, pflag); |
679 | break; | 672 | break; |
680 | case I_PUT: | 673 | case I_PUT: |
681 | err = process_put(in, out, path1, path2, *pwd, pflag); | 674 | err = process_put(conn, path1, path2, *pwd, pflag); |
682 | break; | 675 | break; |
683 | case I_RENAME: | 676 | case I_RENAME: |
684 | path1 = make_absolute(path1, *pwd); | 677 | path1 = make_absolute(path1, *pwd); |
685 | path2 = make_absolute(path2, *pwd); | 678 | path2 = make_absolute(path2, *pwd); |
686 | err = do_rename(in, out, path1, path2); | 679 | err = do_rename(conn, path1, path2); |
687 | break; | 680 | break; |
688 | case I_SYMLINK: | 681 | case I_SYMLINK: |
689 | if (version < 3) { | 682 | path2 = make_absolute(path2, *pwd); |
690 | error("The server (version %d) does not support " | 683 | err = do_symlink(conn, path1, path2); |
691 | "this operation", version); | ||
692 | err = -1; | ||
693 | } else { | ||
694 | path2 = make_absolute(path2, *pwd); | ||
695 | err = do_symlink(in, out, path1, path2); | ||
696 | } | ||
697 | break; | 684 | break; |
698 | case I_RM: | 685 | case I_RM: |
699 | path1 = make_absolute(path1, *pwd); | 686 | path1 = make_absolute(path1, *pwd); |
700 | remote_glob(in, out, path1, GLOB_NOCHECK, NULL, &g); | 687 | remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); |
701 | for (i = 0; g.gl_pathv[i]; i++) { | 688 | for (i = 0; g.gl_pathv[i]; i++) { |
702 | printf("Removing %s\n", g.gl_pathv[i]); | 689 | printf("Removing %s\n", g.gl_pathv[i]); |
703 | if (do_rm(in, out, g.gl_pathv[i]) == -1) | 690 | if (do_rm(conn, g.gl_pathv[i]) == -1) |
704 | err = -1; | 691 | err = -1; |
705 | } | 692 | } |
706 | break; | 693 | break; |
@@ -709,19 +696,19 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd) | |||
709 | attrib_clear(&a); | 696 | attrib_clear(&a); |
710 | a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; | 697 | a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; |
711 | a.perm = 0777; | 698 | a.perm = 0777; |
712 | err = do_mkdir(in, out, path1, &a); | 699 | err = do_mkdir(conn, path1, &a); |
713 | break; | 700 | break; |
714 | case I_RMDIR: | 701 | case I_RMDIR: |
715 | path1 = make_absolute(path1, *pwd); | 702 | path1 = make_absolute(path1, *pwd); |
716 | err = do_rmdir(in, out, path1); | 703 | err = do_rmdir(conn, path1); |
717 | break; | 704 | break; |
718 | case I_CHDIR: | 705 | case I_CHDIR: |
719 | path1 = make_absolute(path1, *pwd); | 706 | path1 = make_absolute(path1, *pwd); |
720 | if ((tmp = do_realpath(in, out, path1)) == NULL) { | 707 | if ((tmp = do_realpath(conn, path1)) == NULL) { |
721 | err = 1; | 708 | err = 1; |
722 | break; | 709 | break; |
723 | } | 710 | } |
724 | if ((aa = do_stat(in, out, tmp, 0)) == NULL) { | 711 | if ((aa = do_stat(conn, tmp, 0)) == NULL) { |
725 | xfree(tmp); | 712 | xfree(tmp); |
726 | err = 1; | 713 | err = 1; |
727 | break; | 714 | break; |
@@ -744,22 +731,22 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd) | |||
744 | break; | 731 | break; |
745 | case I_LS: | 732 | case I_LS: |
746 | if (!path1) { | 733 | if (!path1) { |
747 | do_ls(in, out, *pwd); | 734 | do_ls(conn, *pwd); |
748 | break; | 735 | break; |
749 | } | 736 | } |
750 | path1 = make_absolute(path1, *pwd); | 737 | path1 = make_absolute(path1, *pwd); |
751 | if ((tmp = do_realpath(in, out, path1)) == NULL) | 738 | if ((tmp = do_realpath(conn, path1)) == NULL) |
752 | break; | 739 | break; |
753 | xfree(path1); | 740 | xfree(path1); |
754 | path1 = tmp; | 741 | path1 = tmp; |
755 | if ((aa = do_stat(in, out, path1, 0)) == NULL) | 742 | if ((aa = do_stat(conn, path1, 0)) == NULL) |
756 | break; | 743 | break; |
757 | if ((aa->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && | 744 | if ((aa->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && |
758 | !S_ISDIR(aa->perm)) { | 745 | !S_ISDIR(aa->perm)) { |
759 | error("Can't ls: \"%s\" is not a directory", path1); | 746 | error("Can't ls: \"%s\" is not a directory", path1); |
760 | break; | 747 | break; |
761 | } | 748 | } |
762 | do_ls(in, out, path1); | 749 | do_ls(conn, path1); |
763 | break; | 750 | break; |
764 | case I_LCHDIR: | 751 | case I_LCHDIR: |
765 | if (chdir(path1) == -1) { | 752 | if (chdir(path1) == -1) { |
@@ -790,17 +777,17 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd) | |||
790 | attrib_clear(&a); | 777 | attrib_clear(&a); |
791 | a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; | 778 | a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; |
792 | a.perm = n_arg; | 779 | a.perm = n_arg; |
793 | remote_glob(in, out, path1, GLOB_NOCHECK, NULL, &g); | 780 | remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); |
794 | for (i = 0; g.gl_pathv[i]; i++) { | 781 | for (i = 0; g.gl_pathv[i]; i++) { |
795 | printf("Changing mode on %s\n", g.gl_pathv[i]); | 782 | printf("Changing mode on %s\n", g.gl_pathv[i]); |
796 | do_setstat(in, out, g.gl_pathv[i], &a); | 783 | do_setstat(conn, g.gl_pathv[i], &a); |
797 | } | 784 | } |
798 | break; | 785 | break; |
799 | case I_CHOWN: | 786 | case I_CHOWN: |
800 | path1 = make_absolute(path1, *pwd); | 787 | path1 = make_absolute(path1, *pwd); |
801 | remote_glob(in, out, path1, GLOB_NOCHECK, NULL, &g); | 788 | remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); |
802 | for (i = 0; g.gl_pathv[i]; i++) { | 789 | for (i = 0; g.gl_pathv[i]; i++) { |
803 | if (!(aa = do_stat(in, out, g.gl_pathv[i], 0))) | 790 | if (!(aa = do_stat(conn, g.gl_pathv[i], 0))) |
804 | continue; | 791 | continue; |
805 | if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) { | 792 | if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) { |
806 | error("Can't get current ownership of " | 793 | error("Can't get current ownership of " |
@@ -810,14 +797,14 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd) | |||
810 | printf("Changing owner on %s\n", g.gl_pathv[i]); | 797 | printf("Changing owner on %s\n", g.gl_pathv[i]); |
811 | aa->flags &= SSH2_FILEXFER_ATTR_UIDGID; | 798 | aa->flags &= SSH2_FILEXFER_ATTR_UIDGID; |
812 | aa->uid = n_arg; | 799 | aa->uid = n_arg; |
813 | do_setstat(in, out, g.gl_pathv[i], aa); | 800 | do_setstat(conn, g.gl_pathv[i], aa); |
814 | } | 801 | } |
815 | break; | 802 | break; |
816 | case I_CHGRP: | 803 | case I_CHGRP: |
817 | path1 = make_absolute(path1, *pwd); | 804 | path1 = make_absolute(path1, *pwd); |
818 | remote_glob(in, out, path1, GLOB_NOCHECK, NULL, &g); | 805 | remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); |
819 | for (i = 0; g.gl_pathv[i]; i++) { | 806 | for (i = 0; g.gl_pathv[i]; i++) { |
820 | if (!(aa = do_stat(in, out, g.gl_pathv[i], 0))) | 807 | if (!(aa = do_stat(conn, g.gl_pathv[i], 0))) |
821 | continue; | 808 | continue; |
822 | if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) { | 809 | if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) { |
823 | error("Can't get current ownership of " | 810 | error("Can't get current ownership of " |
@@ -827,7 +814,7 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd) | |||
827 | printf("Changing group on %s\n", g.gl_pathv[i]); | 814 | printf("Changing group on %s\n", g.gl_pathv[i]); |
828 | aa->flags &= SSH2_FILEXFER_ATTR_UIDGID; | 815 | aa->flags &= SSH2_FILEXFER_ATTR_UIDGID; |
829 | aa->gid = n_arg; | 816 | aa->gid = n_arg; |
830 | do_setstat(in, out, g.gl_pathv[i], aa); | 817 | do_setstat(conn, g.gl_pathv[i], aa); |
831 | } | 818 | } |
832 | break; | 819 | break; |
833 | case I_PWD: | 820 | case I_PWD: |
@@ -847,7 +834,7 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd) | |||
847 | help(); | 834 | help(); |
848 | break; | 835 | break; |
849 | case I_VERSION: | 836 | case I_VERSION: |
850 | printf("SFTP protocol version %d\n", version); | 837 | printf("SFTP protocol version %d\n", sftp_proto_version(conn)); |
851 | break; | 838 | break; |
852 | default: | 839 | default: |
853 | fatal("%d is not implemented", cmdnum); | 840 | fatal("%d is not implemented", cmdnum); |
@@ -873,12 +860,13 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2) | |||
873 | char *pwd; | 860 | char *pwd; |
874 | char *dir = NULL; | 861 | char *dir = NULL; |
875 | char cmd[2048]; | 862 | char cmd[2048]; |
863 | struct sftp_conn *conn; | ||
876 | 864 | ||
877 | version = do_init(fd_in, fd_out); | 865 | conn = do_init(fd_in, fd_out, copy_buffer_len, num_requests); |
878 | if (version == -1) | 866 | if (conn == NULL) |
879 | fatal("Couldn't initialise connection to server"); | 867 | fatal("Couldn't initialise connection to server"); |
880 | 868 | ||
881 | pwd = do_realpath(fd_in, fd_out, "."); | 869 | pwd = do_realpath(conn, "."); |
882 | if (pwd == NULL) | 870 | if (pwd == NULL) |
883 | fatal("Need cwd"); | 871 | fatal("Need cwd"); |
884 | 872 | ||
@@ -886,10 +874,10 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2) | |||
886 | dir = xstrdup(file1); | 874 | dir = xstrdup(file1); |
887 | dir = make_absolute(dir, pwd); | 875 | dir = make_absolute(dir, pwd); |
888 | 876 | ||
889 | if (remote_is_dir(fd_in, fd_out, dir) && file2 == NULL) { | 877 | if (remote_is_dir(conn, dir) && file2 == NULL) { |
890 | printf("Changing to: %s\n", dir); | 878 | printf("Changing to: %s\n", dir); |
891 | snprintf(cmd, sizeof cmd, "cd \"%s\"", dir); | 879 | snprintf(cmd, sizeof cmd, "cd \"%s\"", dir); |
892 | parse_dispatch_command(fd_in, fd_out, cmd, &pwd); | 880 | parse_dispatch_command(conn, cmd, &pwd); |
893 | } else { | 881 | } else { |
894 | if (file2 == NULL) | 882 | if (file2 == NULL) |
895 | snprintf(cmd, sizeof cmd, "get %s", dir); | 883 | snprintf(cmd, sizeof cmd, "get %s", dir); |
@@ -897,7 +885,7 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2) | |||
897 | snprintf(cmd, sizeof cmd, "get %s %s", dir, | 885 | snprintf(cmd, sizeof cmd, "get %s %s", dir, |
898 | file2); | 886 | file2); |
899 | 887 | ||
900 | parse_dispatch_command(fd_in, fd_out, cmd, &pwd); | 888 | parse_dispatch_command(conn, cmd, &pwd); |
901 | return; | 889 | return; |
902 | } | 890 | } |
903 | } | 891 | } |
@@ -925,7 +913,7 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2) | |||
925 | if (cp) | 913 | if (cp) |
926 | *cp = '\0'; | 914 | *cp = '\0'; |
927 | 915 | ||
928 | if (parse_dispatch_command(fd_in, fd_out, cmd, &pwd)) | 916 | if (parse_dispatch_command(conn, cmd, &pwd)) |
929 | break; | 917 | break; |
930 | } | 918 | } |
931 | xfree(pwd); | 919 | xfree(pwd); |