~ubuntu-branches/ubuntu/lucid/openssh/lucid

« back to all changes in this revision

Viewing changes to scp.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson
  • Date: 2008-09-30 23:09:58 UTC
  • mfrom: (1.13.3 upstream) (29 hardy)
  • mto: This revision was merged to the branch mainline in revision 43.
  • Revision ID: james.westby@ubuntu.com-20080930230958-o6vsgn8c4mm959s0
Tags: 1:5.1p1-3
* Remove unnecessary ssh-vulnkey output in non-verbose mode when no
  compromised or unknown keys were found (closes: #496495).
* Configure with --disable-strip; dh_strip will deal with stripping
  binaries and will honour DEB_BUILD_OPTIONS (thanks, Bernhard R. Link;
  closes: #498681).
* Fix handling of zero-length server banners (thanks, Tomas Mraz; closes:
  #497026).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $OpenBSD: scp.c,v 1.156 2007/01/22 13:06:21 djm Exp $ */
 
1
/* $OpenBSD: scp.c,v 1.163 2008/06/13 18:55:22 dtucker Exp $ */
2
2
/*
3
3
 * scp - secure remote copy.  This is basically patched BSD rcp which
4
4
 * uses ssh to do the data transfer (instead of using rcmd).
78
78
#ifdef HAVE_SYS_STAT_H
79
79
# include <sys/stat.h>
80
80
#endif
 
81
#ifdef HAVE_POLL_H
 
82
#include <poll.h>
 
83
#else
 
84
# ifdef HAVE_SYS_POLL_H
 
85
#  include <sys/poll.h>
 
86
# endif
 
87
#endif
81
88
#ifdef HAVE_SYS_TIME_H
82
89
# include <sys/time.h>
83
90
#endif
96
103
#include <string.h>
97
104
#include <time.h>
98
105
#include <unistd.h>
 
106
#if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H)
 
107
#include <vis.h>
 
108
#endif
99
109
 
100
110
#include "xmalloc.h"
101
111
#include "atomicio.h"
106
116
 
107
117
extern char *__progname;
108
118
 
 
119
#define COPY_BUFLEN     16384
 
120
 
109
121
int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout);
110
122
 
111
123
void bwlimit(int);
156
168
 
157
169
        if (verbose_mode) {
158
170
                fprintf(stderr, "Executing:");
159
 
                for (i = 0; i < a->num; i++)
160
 
                        fprintf(stderr, " %s", a->list[i]);
 
171
                for (i = 0; i < a->num; i++) {
 
172
                        if (i == 0)
 
173
                                fprintf(stderr, " %s", a->list[i]);
 
174
                        else
 
175
                                /*
 
176
                                 * TODO: misbehaves if a->list[i] contains a
 
177
                                 * single quote
 
178
                                 */
 
179
                                fprintf(stderr, " '%s'", a->list[i]);
 
180
                }
161
181
                fprintf(stderr, "\n");
162
182
        }
163
183
        if ((pid = fork()) == -1)
279
299
void source(int, char *[]);
280
300
void tolocal(int, char *[]);
281
301
void toremote(char *, int, char *[]);
 
302
size_t scpio(ssize_t (*)(int, void *, size_t), int, void *, size_t, off_t *);
282
303
void usage(void);
283
304
 
284
305
int
438
459
        exit(errs != 0);
439
460
}
440
461
 
 
462
/*
 
463
 * atomicio-like wrapper that also applies bandwidth limits and updates
 
464
 * the progressmeter counter.
 
465
 */
 
466
size_t
 
467
scpio(ssize_t (*f)(int, void *, size_t), int fd, void *_p, size_t l, off_t *c)
 
468
{
 
469
        u_char *p = (u_char *)_p;
 
470
        size_t offset;
 
471
        ssize_t r;
 
472
        struct pollfd pfd;
 
473
 
 
474
        pfd.fd = fd;
 
475
        pfd.events = f == read ? POLLIN : POLLOUT;
 
476
        for (offset = 0; offset < l;) {
 
477
                r = f(fd, p + offset, l - offset);
 
478
                if (r == 0) {
 
479
                        errno = EPIPE;
 
480
                        return offset;
 
481
                }
 
482
                if (r < 0) {
 
483
                        if (errno == EINTR)
 
484
                                continue;
 
485
                        if (errno == EAGAIN || errno == EWOULDBLOCK) {
 
486
                                (void)poll(&pfd, 1, -1); /* Ignore errors */
 
487
                                continue;
 
488
                        }
 
489
                        return offset;
 
490
                }
 
491
                offset += (size_t)r;
 
492
                *c += (off_t)r;
 
493
                if (limit_rate)
 
494
                        bwlimit(r);
 
495
        }
 
496
        return offset;
 
497
}
 
498
 
441
499
void
442
500
toremote(char *targ, int argc, char **argv)
443
501
{
579
637
        struct stat stb;
580
638
        static BUF buffer;
581
639
        BUF *bp;
582
 
        off_t i, amt, statbytes;
583
 
        size_t result;
 
640
        off_t i, statbytes;
 
641
        size_t amt;
584
642
        int fd = -1, haderr, indx;
585
 
        char *last, *name, buf[2048];
 
643
        char *last, *name, buf[2048], encname[MAXPATHLEN];
586
644
        int len;
587
645
 
588
646
        for (indx = 0; indx < argc; ++indx) {
591
649
                len = strlen(name);
592
650
                while (len > 1 && name[len-1] == '/')
593
651
                        name[--len] = '\0';
 
652
                if ((fd = open(name, O_RDONLY|O_NONBLOCK, 0)) < 0)
 
653
                        goto syserr;
594
654
                if (strchr(name, '\n') != NULL) {
595
 
                        run_err("%s: skipping, filename contains a newline",
596
 
                            name);
597
 
                        goto next;
 
655
                        strnvis(encname, name, sizeof(encname), VIS_NL);
 
656
                        name = encname;
598
657
                }
599
 
                if ((fd = open(name, O_RDONLY, 0)) < 0)
600
 
                        goto syserr;
601
658
                if (fstat(fd, &stb) < 0) {
602
659
syserr:                 run_err("%s: %s", name, strerror(errno));
603
660
                        goto next;
604
661
                }
 
662
                if (stb.st_size < 0) {
 
663
                        run_err("%s: %s", name, "Negative file size");
 
664
                        goto next;
 
665
                }
 
666
                unset_nonblock(fd);
605
667
                switch (stb.st_mode & S_IFMT) {
606
668
                case S_IFREG:
607
669
                        break;
626
688
                         * versions expecting microseconds.
627
689
                         */
628
690
                        (void) snprintf(buf, sizeof buf, "T%lu 0 %lu 0\n",
629
 
                            (u_long) stb.st_mtime,
630
 
                            (u_long) stb.st_atime);
 
691
                            (u_long) (stb.st_mtime < 0 ? 0 : stb.st_mtime),
 
692
                            (u_long) (stb.st_atime < 0 ? 0 : stb.st_atime));
 
693
                        if (verbose_mode) {
 
694
                                fprintf(stderr, "File mtime %ld atime %ld\n",
 
695
                                    (long)stb.st_mtime, (long)stb.st_atime);
 
696
                                fprintf(stderr, "Sending file timestamps: %s",
 
697
                                    buf);
 
698
                        }
631
699
                        (void) atomicio(vwrite, remout, buf, strlen(buf));
632
700
                        if (response() < 0)
633
701
                                goto next;
642
710
                (void) atomicio(vwrite, remout, buf, strlen(buf));
643
711
                if (response() < 0)
644
712
                        goto next;
645
 
                if ((bp = allocbuf(&buffer, fd, 2048)) == NULL) {
 
713
                if ((bp = allocbuf(&buffer, fd, COPY_BUFLEN)) == NULL) {
646
714
next:                   if (fd != -1) {
647
715
                                (void) close(fd);
648
716
                                fd = -1;
651
719
                }
652
720
                if (showprogress)
653
721
                        start_progress_meter(curfile, stb.st_size, &statbytes);
654
 
                /* Keep writing after an error so that we stay sync'd up. */
 
722
                set_nonblock(remout);
655
723
                for (haderr = i = 0; i < stb.st_size; i += bp->cnt) {
656
724
                        amt = bp->cnt;
657
 
                        if (i + amt > stb.st_size)
 
725
                        if (i + (off_t)amt > stb.st_size)
658
726
                                amt = stb.st_size - i;
659
727
                        if (!haderr) {
660
 
                                result = atomicio(read, fd, bp->buf, amt);
661
 
                                if (result != amt)
662
 
                                        haderr = errno;
663
 
                        }
664
 
                        if (haderr)
665
 
                                (void) atomicio(vwrite, remout, bp->buf, amt);
666
 
                        else {
667
 
                                result = atomicio(vwrite, remout, bp->buf, amt);
668
 
                                if (result != amt)
669
 
                                        haderr = errno;
670
 
                                statbytes += result;
671
 
                        }
672
 
                        if (limit_rate)
673
 
                                bwlimit(amt);
 
728
                                if (atomicio(read, fd, bp->buf, amt) != amt)
 
729
                                        haderr = errno;
 
730
                        }
 
731
                        /* Keep writing after error to retain sync */
 
732
                        if (haderr) {
 
733
                                (void)atomicio(vwrite, remout, bp->buf, amt);
 
734
                                continue;
 
735
                        }
 
736
                        if (scpio(vwrite, remout, bp->buf, amt,
 
737
                            &statbytes) != amt)
 
738
                                haderr = errno;
674
739
                }
 
740
                unset_nonblock(remout);
675
741
                if (showprogress)
676
742
                        stop_progress_meter();
677
743
 
777
843
                        thresh /= 2;
778
844
                        if (thresh < 2048)
779
845
                                thresh = 2048;
780
 
                } else if (bwend.tv_usec < 100) {
 
846
                } else if (bwend.tv_usec < 10000) {
781
847
                        thresh *= 2;
782
 
                        if (thresh > 32768)
783
 
                                thresh = 32768;
 
848
                        if (thresh > COPY_BUFLEN * 4)
 
849
                                thresh = COPY_BUFLEN * 4;
784
850
                }
785
851
 
786
852
                TIMEVAL_TO_TIMESPEC(&bwend, &ts);
971
1037
                        continue;
972
1038
                }
973
1039
                (void) atomicio(vwrite, remout, "", 1);
974
 
                if ((bp = allocbuf(&buffer, ofd, 4096)) == NULL) {
 
1040
                if ((bp = allocbuf(&buffer, ofd, COPY_BUFLEN)) == NULL) {
975
1041
                        (void) close(ofd);
976
1042
                        continue;
977
1043
                }
981
1047
                statbytes = 0;
982
1048
                if (showprogress)
983
1049
                        start_progress_meter(curfile, size, &statbytes);
984
 
                for (count = i = 0; i < size; i += 4096) {
985
 
                        amt = 4096;
 
1050
                set_nonblock(remin);
 
1051
                for (count = i = 0; i < size; i += bp->cnt) {
 
1052
                        amt = bp->cnt;
986
1053
                        if (i + amt > size)
987
1054
                                amt = size - i;
988
1055
                        count += amt;
989
1056
                        do {
990
 
                                j = atomicio(read, remin, cp, amt);
 
1057
                                j = scpio(read, remin, cp, amt, &statbytes);
991
1058
                                if (j == 0) {
992
 
                                        run_err("%s", j ? strerror(errno) :
 
1059
                                        run_err("%s", j != EPIPE ?
 
1060
                                            strerror(errno) :
993
1061
                                            "dropped connection");
994
1062
                                        exit(1);
995
1063
                                }
996
1064
                                amt -= j;
997
1065
                                cp += j;
998
 
                                statbytes += j;
999
1066
                        } while (amt > 0);
1000
1067
 
1001
 
                        if (limit_rate)
1002
 
                                bwlimit(4096);
1003
 
 
1004
1068
                        if (count == bp->cnt) {
1005
1069
                                /* Keep reading so we stay sync'd up. */
1006
1070
                                if (wrerr == NO) {
1014
1078
                                cp = bp->buf;
1015
1079
                        }
1016
1080
                }
 
1081
                unset_nonblock(remin);
1017
1082
                if (showprogress)
1018
1083
                        stop_progress_meter();
1019
1084
                if (count != 0 && wrerr == NO &&
1021
1086
                        wrerr = YES;
1022
1087
                        wrerrno = errno;
1023
1088
                }
1024
 
                if (wrerr == NO && ftruncate(ofd, size) != 0) {
 
1089
                if (wrerr == NO && (!exists || S_ISREG(stb.st_mode)) &&
 
1090
                    ftruncate(ofd, size) != 0) {
1025
1091
                        run_err("%s: truncate: %s", np, strerror(errno));
1026
1092
                        wrerr = DISPLAYED;
1027
1093
                }
1116
1182
        (void) fprintf(stderr,
1117
1183
            "usage: scp [-1246BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]\n"
1118
1184
            "           [-l limit] [-o ssh_option] [-P port] [-S program]\n"
1119
 
            "           [[user@]host1:]file1 [...] [[user@]host2:]file2\n");
 
1185
            "           [[user@]host1:]file1 ... [[user@]host2:]file2\n");
1120
1186
        exit(1);
1121
1187
}
1122
1188