|
Lines 73-78
Link Here
|
| 73 |
|
73 |
|
| 74 |
#include <sys/param.h> |
74 |
#include <sys/param.h> |
| 75 |
#include <sys/types.h> |
75 |
#include <sys/types.h> |
|
|
76 |
#include <sys/poll.h> |
| 76 |
#include <sys/wait.h> |
77 |
#include <sys/wait.h> |
| 77 |
#include <sys/stat.h> |
78 |
#include <sys/stat.h> |
| 78 |
#include <sys/time.h> |
79 |
#include <sys/time.h> |
|
Lines 98-103
Link Here
|
| 98 |
#include "misc.h" |
99 |
#include "misc.h" |
| 99 |
#include "progressmeter.h" |
100 |
#include "progressmeter.h" |
| 100 |
|
101 |
|
|
|
102 |
#define SCP_BUFLEN 16384 |
| 103 |
|
| 101 |
int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout); |
104 |
int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout); |
| 102 |
|
105 |
|
| 103 |
void bwlimit(int); |
106 |
void bwlimit(int); |
|
Lines 271-276
void sink(int, char *[]);
Link Here
|
| 271 |
void source(int, char *[]); |
274 |
void source(int, char *[]); |
| 272 |
void tolocal(int, char *[]); |
275 |
void tolocal(int, char *[]); |
| 273 |
void toremote(char *, int, char *[]); |
276 |
void toremote(char *, int, char *[]); |
|
|
277 |
size_t scpio(ssize_t (*)(int, void *, size_t), int, void *, size_t, off_t *); |
| 274 |
void usage(void); |
278 |
void usage(void); |
| 275 |
|
279 |
|
| 276 |
int |
280 |
int |
|
Lines 425-430
main(int argc, char **argv)
Link Here
|
| 425 |
exit(errs != 0); |
429 |
exit(errs != 0); |
| 426 |
} |
430 |
} |
| 427 |
|
431 |
|
|
|
432 |
/* |
| 433 |
* atomicio-like wrapper that also applies bandwidth limits and updates |
| 434 |
* the progressmeter counter. |
| 435 |
*/ |
| 436 |
size_t |
| 437 |
scpio(ssize_t (*f)(int, void *, size_t), int fd, void *_p, size_t l, off_t *c) |
| 438 |
{ |
| 439 |
u_char *p = (u_char *)_p; |
| 440 |
size_t o; |
| 441 |
ssize_t r; |
| 442 |
struct pollfd pfd; |
| 443 |
|
| 444 |
pfd.fd = fd; |
| 445 |
pfd.events = f == read ? POLLIN : POLLOUT; |
| 446 |
for (o = 0; o < l;) { |
| 447 |
if (poll(&pfd, 1, -1) == -1) { |
| 448 |
if (errno == EINTR) |
| 449 |
continue; |
| 450 |
fatal("%s: poll: %s", __func__, strerror(errno)); |
| 451 |
} |
| 452 |
r = f(fd, p + o, l - o); |
| 453 |
if (r == 0) { |
| 454 |
errno = EPIPE; |
| 455 |
return o; |
| 456 |
} |
| 457 |
if (r < 0) { |
| 458 |
if (errno == EINTR || errno == EAGAIN) |
| 459 |
continue; |
| 460 |
return 0; |
| 461 |
} |
| 462 |
o += (size_t)r; |
| 463 |
*c += (off_t)r; |
| 464 |
if (limit_rate) |
| 465 |
bwlimit(r); |
| 466 |
} |
| 467 |
return o; |
| 468 |
} |
| 469 |
|
| 428 |
void |
470 |
void |
| 429 |
toremote(char *targ, int argc, char **argv) |
471 |
toremote(char *targ, int argc, char **argv) |
| 430 |
{ |
472 |
{ |
|
Lines 567-573
source(int argc, char **argv)
Link Here
|
| 567 |
static BUF buffer; |
609 |
static BUF buffer; |
| 568 |
BUF *bp; |
610 |
BUF *bp; |
| 569 |
off_t i, amt, statbytes; |
611 |
off_t i, amt, statbytes; |
| 570 |
size_t result; |
|
|
| 571 |
int fd = -1, haderr, indx; |
612 |
int fd = -1, haderr, indx; |
| 572 |
char *last, *name, buf[2048]; |
613 |
char *last, *name, buf[2048]; |
| 573 |
int len; |
614 |
int len; |
|
Lines 629-635
syserr: run_err("%s: %s", name, strerr
Link Here
|
| 629 |
(void) atomicio(vwrite, remout, buf, strlen(buf)); |
670 |
(void) atomicio(vwrite, remout, buf, strlen(buf)); |
| 630 |
if (response() < 0) |
671 |
if (response() < 0) |
| 631 |
goto next; |
672 |
goto next; |
| 632 |
if ((bp = allocbuf(&buffer, fd, 2048)) == NULL) { |
673 |
if ((bp = allocbuf(&buffer, fd, SCP_BUFLEN)) == NULL) { |
| 633 |
next: if (fd != -1) { |
674 |
next: if (fd != -1) { |
| 634 |
(void) close(fd); |
675 |
(void) close(fd); |
| 635 |
fd = -1; |
676 |
fd = -1; |
|
Lines 638-664
next: if (fd != -1) {
Link Here
|
| 638 |
} |
679 |
} |
| 639 |
if (showprogress) |
680 |
if (showprogress) |
| 640 |
start_progress_meter(curfile, stb.st_size, &statbytes); |
681 |
start_progress_meter(curfile, stb.st_size, &statbytes); |
| 641 |
/* Keep writing after an error so that we stay sync'd up. */ |
682 |
set_nonblock(remout); |
| 642 |
for (haderr = i = 0; i < stb.st_size; i += bp->cnt) { |
683 |
for (haderr = i = 0; i < stb.st_size; i += bp->cnt) { |
| 643 |
amt = bp->cnt; |
684 |
amt = bp->cnt; |
| 644 |
if (i + amt > stb.st_size) |
685 |
if (i + amt > stb.st_size) |
| 645 |
amt = stb.st_size - i; |
686 |
amt = stb.st_size - i; |
| 646 |
if (!haderr) { |
687 |
if (!haderr) { |
| 647 |
result = atomicio(read, fd, bp->buf, amt); |
688 |
if (atomicio(read, fd, bp->buf, amt) != amt) |
| 648 |
if (result != amt) |
|
|
| 649 |
haderr = errno; |
689 |
haderr = errno; |
| 650 |
} |
690 |
} |
| 651 |
if (haderr) |
691 |
/* Keep writing after error to retain sync */ |
| 652 |
(void) atomicio(vwrite, remout, bp->buf, amt); |
692 |
if (haderr) { |
| 653 |
else { |
693 |
(void)atomicio(vwrite, remout, bp->buf, amt); |
| 654 |
result = atomicio(vwrite, remout, bp->buf, amt); |
694 |
continue; |
| 655 |
if (result != amt) |
|
|
| 656 |
haderr = errno; |
| 657 |
statbytes += result; |
| 658 |
} |
695 |
} |
| 659 |
if (limit_rate) |
696 |
if (scpio(vwrite, remout, bp->buf, amt, |
| 660 |
bwlimit(amt); |
697 |
&statbytes) != amt) |
|
|
698 |
haderr = errno; |
| 661 |
} |
699 |
} |
|
|
700 |
unset_nonblock(remout); |
| 662 |
if (showprogress) |
701 |
if (showprogress) |
| 663 |
stop_progress_meter(); |
702 |
stop_progress_meter(); |
| 664 |
|
703 |
|
|
Lines 764-773
bwlimit(int amount)
Link Here
|
| 764 |
thresh /= 2; |
803 |
thresh /= 2; |
| 765 |
if (thresh < 2048) |
804 |
if (thresh < 2048) |
| 766 |
thresh = 2048; |
805 |
thresh = 2048; |
| 767 |
} else if (bwend.tv_usec < 100) { |
806 |
} else if (bwend.tv_usec < 10000) { |
| 768 |
thresh *= 2; |
807 |
thresh *= 2; |
| 769 |
if (thresh > 32768) |
808 |
if (thresh > SCP_BUFLEN * 4) |
| 770 |
thresh = 32768; |
809 |
thresh = SCP_BUFLEN * 4; |
| 771 |
} |
810 |
} |
| 772 |
|
811 |
|
| 773 |
TIMEVAL_TO_TIMESPEC(&bwend, &ts); |
812 |
TIMEVAL_TO_TIMESPEC(&bwend, &ts); |
|
Lines 958-964
bad: run_err("%s: %s", np, strerror(er
Link Here
|
| 958 |
continue; |
997 |
continue; |
| 959 |
} |
998 |
} |
| 960 |
(void) atomicio(vwrite, remout, "", 1); |
999 |
(void) atomicio(vwrite, remout, "", 1); |
| 961 |
if ((bp = allocbuf(&buffer, ofd, 4096)) == NULL) { |
1000 |
if ((bp = allocbuf(&buffer, ofd, SCP_BUFLEN)) == NULL) { |
| 962 |
(void) close(ofd); |
1001 |
(void) close(ofd); |
| 963 |
continue; |
1002 |
continue; |
| 964 |
} |
1003 |
} |
|
Lines 968-993
bad: run_err("%s: %s", np, strerror(er
Link Here
|
| 968 |
statbytes = 0; |
1007 |
statbytes = 0; |
| 969 |
if (showprogress) |
1008 |
if (showprogress) |
| 970 |
start_progress_meter(curfile, size, &statbytes); |
1009 |
start_progress_meter(curfile, size, &statbytes); |
| 971 |
for (count = i = 0; i < size; i += 4096) { |
1010 |
set_nonblock(remin); |
| 972 |
amt = 4096; |
1011 |
for (count = i = 0; i < size; i += bp->cnt) { |
|
|
1012 |
amt = bp->cnt; |
| 973 |
if (i + amt > size) |
1013 |
if (i + amt > size) |
| 974 |
amt = size - i; |
1014 |
amt = size - i; |
| 975 |
count += amt; |
1015 |
count += amt; |
| 976 |
do { |
1016 |
do { |
| 977 |
j = atomicio(read, remin, cp, amt); |
1017 |
j = scpio(read, remin, cp, amt, &statbytes); |
| 978 |
if (j == 0) { |
1018 |
if (j == 0) { |
| 979 |
run_err("%s", j ? strerror(errno) : |
1019 |
run_err("%s", j != EPIPE ? |
|
|
1020 |
strerror(errno) : |
| 980 |
"dropped connection"); |
1021 |
"dropped connection"); |
| 981 |
exit(1); |
1022 |
exit(1); |
| 982 |
} |
1023 |
} |
| 983 |
amt -= j; |
1024 |
amt -= j; |
| 984 |
cp += j; |
1025 |
cp += j; |
| 985 |
statbytes += j; |
|
|
| 986 |
} while (amt > 0); |
1026 |
} while (amt > 0); |
| 987 |
|
1027 |
|
| 988 |
if (limit_rate) |
|
|
| 989 |
bwlimit(4096); |
| 990 |
|
| 991 |
if (count == bp->cnt) { |
1028 |
if (count == bp->cnt) { |
| 992 |
/* Keep reading so we stay sync'd up. */ |
1029 |
/* Keep reading so we stay sync'd up. */ |
| 993 |
if (wrerr == NO) { |
1030 |
if (wrerr == NO) { |
|
Lines 1001-1006
bad: run_err("%s: %s", np, strerror(er
Link Here
|
| 1001 |
cp = bp->buf; |
1038 |
cp = bp->buf; |
| 1002 |
} |
1039 |
} |
| 1003 |
} |
1040 |
} |
|
|
1041 |
unset_nonblock(remin); |
| 1004 |
if (showprogress) |
1042 |
if (showprogress) |
| 1005 |
stop_progress_meter(); |
1043 |
stop_progress_meter(); |
| 1006 |
if (count != 0 && wrerr == NO && |
1044 |
if (count != 0 && wrerr == NO && |