version 1.166, 2010/07/01 13:06:59 |
version 1.167, 2010/09/22 22:58:51 |
|
|
|
|
int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout); |
int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout); |
|
|
void bwlimit(int); |
|
|
|
/* Struct for addargs */ |
/* Struct for addargs */ |
arglist args; |
arglist args; |
|
|
/* Bandwidth limit */ |
/* Bandwidth limit */ |
off_t limit_rate = 0; |
long long limit_kbps = 0; |
|
struct bwlimit bwlimit; |
|
|
/* Name of current file being transferred. */ |
/* Name of current file being transferred. */ |
char *curfile; |
char *curfile; |
|
|
main(int argc, char **argv) |
main(int argc, char **argv) |
{ |
{ |
int ch, fflag, tflag, status, n; |
int ch, fflag, tflag, status, n; |
double speed; |
char *targ, **newargv; |
char *targ, *endp, **newargv; |
const char *errstr; |
extern char *optarg; |
extern char *optarg; |
extern int optind; |
extern int optind; |
|
|
|
|
addargs(&args, "-oBatchmode yes"); |
addargs(&args, "-oBatchmode yes"); |
break; |
break; |
case 'l': |
case 'l': |
speed = strtod(optarg, &endp); |
limit_kbps = strtonum(optarg, 1, 100 * 1024 * 1024, |
if (speed <= 0 || *endp != '\0') |
&errstr); |
|
if (errstr != NULL) |
usage(); |
usage(); |
limit_rate = speed * 1024; |
limit_kbps *= 1024; /* kbps */ |
|
bandwidth_limit_init(&bwlimit, limit_kbps, COPY_BUFLEN); |
break; |
break; |
case 'p': |
case 'p': |
pflag = 1; |
pflag = 1; |
|
|
exit(errs != 0); |
exit(errs != 0); |
} |
} |
|
|
/* |
/* Callback from atomicio6 to update progress meter and limit bandwidth */ |
* atomicio-like wrapper that also applies bandwidth limits and updates |
static int |
* the progressmeter counter. |
scpio(void *_cnt, size_t s) |
*/ |
|
static size_t |
|
scpio(ssize_t (*f)(int, void *, size_t), int fd, void *_p, size_t l, off_t *c) |
|
{ |
{ |
u_char *p = (u_char *)_p; |
off_t *cnt = (off_t *)_cnt; |
size_t offset; |
|
ssize_t r; |
|
struct pollfd pfd; |
|
|
|
pfd.fd = fd; |
*cnt += s; |
pfd.events = f == read ? POLLIN : POLLOUT; |
if (limit_kbps > 0) |
for (offset = 0; offset < l;) { |
bandwidth_limit(&bwlimit, s); |
r = f(fd, p + offset, l - offset); |
return 0; |
if (r == 0) { |
|
errno = EPIPE; |
|
return offset; |
|
} |
|
if (r < 0) { |
|
if (errno == EINTR) |
|
continue; |
|
if (errno == EAGAIN) { |
|
(void)poll(&pfd, 1, -1); /* Ignore errors */ |
|
continue; |
|
} |
|
return offset; |
|
} |
|
offset += (size_t)r; |
|
*c += (off_t)r; |
|
if (limit_rate) |
|
bwlimit(r); |
|
} |
|
return offset; |
|
} |
} |
|
|
void |
void |
|
|
(void)atomicio(vwrite, remout, bp->buf, amt); |
(void)atomicio(vwrite, remout, bp->buf, amt); |
continue; |
continue; |
} |
} |
if (scpio(vwrite, remout, bp->buf, amt, |
if (atomicio6(vwrite, remout, bp->buf, amt, scpio, |
&statbytes) != amt) |
&statbytes) != amt) |
haderr = errno; |
haderr = errno; |
} |
} |
|
|
} |
} |
|
|
void |
void |
bwlimit(int amount) |
|
{ |
|
static struct timeval bwstart, bwend; |
|
static int lamt, thresh = 16384; |
|
u_int64_t waitlen; |
|
struct timespec ts, rm; |
|
|
|
if (!timerisset(&bwstart)) { |
|
gettimeofday(&bwstart, NULL); |
|
return; |
|
} |
|
|
|
lamt += amount; |
|
if (lamt < thresh) |
|
return; |
|
|
|
gettimeofday(&bwend, NULL); |
|
timersub(&bwend, &bwstart, &bwend); |
|
if (!timerisset(&bwend)) |
|
return; |
|
|
|
lamt *= 8; |
|
waitlen = (double)1000000L * lamt / limit_rate; |
|
|
|
bwstart.tv_sec = waitlen / 1000000L; |
|
bwstart.tv_usec = waitlen % 1000000L; |
|
|
|
if (timercmp(&bwstart, &bwend, >)) { |
|
timersub(&bwstart, &bwend, &bwend); |
|
|
|
/* Adjust the wait time */ |
|
if (bwend.tv_sec) { |
|
thresh /= 2; |
|
if (thresh < 2048) |
|
thresh = 2048; |
|
} else if (bwend.tv_usec < 10000) { |
|
thresh *= 2; |
|
if (thresh > COPY_BUFLEN * 4) |
|
thresh = COPY_BUFLEN * 4; |
|
} |
|
|
|
TIMEVAL_TO_TIMESPEC(&bwend, &ts); |
|
while (nanosleep(&ts, &rm) == -1) { |
|
if (errno != EINTR) |
|
break; |
|
ts = rm; |
|
} |
|
} |
|
|
|
lamt = 0; |
|
gettimeofday(&bwstart, NULL); |
|
} |
|
|
|
void |
|
sink(int argc, char **argv) |
sink(int argc, char **argv) |
{ |
{ |
static BUF buffer; |
static BUF buffer; |
|
|
amt = size - i; |
amt = size - i; |
count += amt; |
count += amt; |
do { |
do { |
j = scpio(read, remin, cp, amt, &statbytes); |
j = atomicio6(read, remin, cp, amt, |
|
scpio, &statbytes); |
if (j == 0) { |
if (j == 0) { |
run_err("%s", j != EPIPE ? |
run_err("%s", j != EPIPE ? |
strerror(errno) : |
strerror(errno) : |