summaryrefslogtreecommitdiffstats
path: root/crypto/openssh/scp.c
diff options
context:
space:
mode:
authordes <des@FreeBSD.org>2008-08-01 02:48:36 +0000
committerdes <des@FreeBSD.org>2008-08-01 02:48:36 +0000
commitb7aa600c416b507a21191efa2689c0a03031d58e (patch)
treeed813bdf7d8dbee35f19092d185e1a2793885204 /crypto/openssh/scp.c
parenta2326b0bec3be2ec01f66d386cfe43139cbc579c (diff)
parent8f6f5baf400f08937451cf9c8ecc220e9efd2f63 (diff)
downloadFreeBSD-src-b7aa600c416b507a21191efa2689c0a03031d58e.zip
FreeBSD-src-b7aa600c416b507a21191efa2689c0a03031d58e.tar.gz
Upgrade to OpenSSH 5.1p1.
I have worked hard to reduce diffs against the vendor branch. One notable change in that respect is that we no longer prefer DSA over RSA - the reasons for doing so went away years ago. This may cause some surprises, as ssh will warn about unknown host keys even for hosts whose keys haven't changed. MFC after: 6 weeks
Diffstat (limited to 'crypto/openssh/scp.c')
-rw-r--r--crypto/openssh/scp.c138
1 files changed, 98 insertions, 40 deletions
diff --git a/crypto/openssh/scp.c b/crypto/openssh/scp.c
index 56a3e79..9f8b7a1 100644
--- a/crypto/openssh/scp.c
+++ b/crypto/openssh/scp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: scp.c,v 1.155 2006/08/03 03:34:42 deraadt Exp $ */
+/* $OpenBSD: scp.c,v 1.163 2008/06/13 18:55:22 dtucker Exp $ */
/*
* scp - secure remote copy. This is basically patched BSD rcp which
* uses ssh to do the data transfer (instead of using rcmd).
@@ -78,6 +78,13 @@
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#else
+# ifdef HAVE_SYS_POLL_H
+# include <sys/poll.h>
+# endif
+#endif
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
@@ -96,6 +103,9 @@
#include <string.h>
#include <time.h>
#include <unistd.h>
+#if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H)
+#include <vis.h>
+#endif
#include "xmalloc.h"
#include "atomicio.h"
@@ -106,6 +116,8 @@
extern char *__progname;
+#define COPY_BUFLEN 16384
+
int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout);
void bwlimit(int);
@@ -279,6 +291,7 @@ void sink(int, char *[]);
void source(int, char *[]);
void tolocal(int, char *[]);
void toremote(char *, int, char *[]);
+size_t scpio(ssize_t (*)(int, void *, size_t), int, void *, size_t, off_t *);
void usage(void);
int
@@ -380,7 +393,7 @@ main(int argc, char **argv)
if ((pwd = getpwuid(userid = getuid())) == NULL)
fatal("unknown user %u", (u_int) userid);
- if (!isatty(STDERR_FILENO))
+ if (!isatty(STDOUT_FILENO))
showprogress = 0;
remin = STDIN_FILENO;
@@ -438,6 +451,43 @@ main(int argc, char **argv)
exit(errs != 0);
}
+/*
+ * atomicio-like wrapper that also applies bandwidth limits and updates
+ * the progressmeter counter.
+ */
+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;
+ size_t offset;
+ ssize_t r;
+ struct pollfd pfd;
+
+ pfd.fd = fd;
+ pfd.events = f == read ? POLLIN : POLLOUT;
+ for (offset = 0; offset < l;) {
+ r = f(fd, p + offset, l - offset);
+ if (r == 0) {
+ errno = EPIPE;
+ return offset;
+ }
+ if (r < 0) {
+ if (errno == EINTR)
+ continue;
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ (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
toremote(char *targ, int argc, char **argv)
{
@@ -579,10 +629,10 @@ source(int argc, char **argv)
struct stat stb;
static BUF buffer;
BUF *bp;
- off_t i, amt, statbytes;
- size_t result;
+ off_t i, statbytes;
+ size_t amt;
int fd = -1, haderr, indx;
- char *last, *name, buf[2048];
+ char *last, *name, buf[2048], encname[MAXPATHLEN];
int len;
for (indx = 0; indx < argc; ++indx) {
@@ -591,17 +641,21 @@ source(int argc, char **argv)
len = strlen(name);
while (len > 1 && name[len-1] == '/')
name[--len] = '\0';
+ if ((fd = open(name, O_RDONLY|O_NONBLOCK, 0)) < 0)
+ goto syserr;
if (strchr(name, '\n') != NULL) {
- run_err("%s: skipping, filename contains a newline",
- name);
- goto next;
+ strnvis(encname, name, sizeof(encname), VIS_NL);
+ name = encname;
}
- if ((fd = open(name, O_RDONLY, 0)) < 0)
- goto syserr;
if (fstat(fd, &stb) < 0) {
syserr: run_err("%s: %s", name, strerror(errno));
goto next;
}
+ if (stb.st_size < 0) {
+ run_err("%s: %s", name, "Negative file size");
+ goto next;
+ }
+ unset_nonblock(fd);
switch (stb.st_mode & S_IFMT) {
case S_IFREG:
break;
@@ -626,8 +680,14 @@ syserr: run_err("%s: %s", name, strerror(errno));
* versions expecting microseconds.
*/
(void) snprintf(buf, sizeof buf, "T%lu 0 %lu 0\n",
- (u_long) stb.st_mtime,
- (u_long) stb.st_atime);
+ (u_long) (stb.st_mtime < 0 ? 0 : stb.st_mtime),
+ (u_long) (stb.st_atime < 0 ? 0 : stb.st_atime));
+ if (verbose_mode) {
+ fprintf(stderr, "File mtime %ld atime %ld\n",
+ (long)stb.st_mtime, (long)stb.st_atime);
+ fprintf(stderr, "Sending file timestamps: %s",
+ buf);
+ }
(void) atomicio(vwrite, remout, buf, strlen(buf));
if (response() < 0)
goto next;
@@ -642,7 +702,7 @@ syserr: run_err("%s: %s", name, strerror(errno));
(void) atomicio(vwrite, remout, buf, strlen(buf));
if (response() < 0)
goto next;
- if ((bp = allocbuf(&buffer, fd, 2048)) == NULL) {
+ if ((bp = allocbuf(&buffer, fd, COPY_BUFLEN)) == NULL) {
next: if (fd != -1) {
(void) close(fd);
fd = -1;
@@ -651,27 +711,25 @@ next: if (fd != -1) {
}
if (showprogress)
start_progress_meter(curfile, stb.st_size, &statbytes);
- /* Keep writing after an error so that we stay sync'd up. */
+ set_nonblock(remout);
for (haderr = i = 0; i < stb.st_size; i += bp->cnt) {
amt = bp->cnt;
- if (i + amt > stb.st_size)
+ if (i + (off_t)amt > stb.st_size)
amt = stb.st_size - i;
if (!haderr) {
- result = atomicio(read, fd, bp->buf, amt);
- if (result != amt)
+ if (atomicio(read, fd, bp->buf, amt) != amt)
haderr = errno;
}
- if (haderr)
- (void) atomicio(vwrite, remout, bp->buf, amt);
- else {
- result = atomicio(vwrite, remout, bp->buf, amt);
- if (result != amt)
- haderr = errno;
- statbytes += result;
+ /* Keep writing after error to retain sync */
+ if (haderr) {
+ (void)atomicio(vwrite, remout, bp->buf, amt);
+ continue;
}
- if (limit_rate)
- bwlimit(amt);
+ if (scpio(vwrite, remout, bp->buf, amt,
+ &statbytes) != amt)
+ haderr = errno;
}
+ unset_nonblock(remout);
if (showprogress)
stop_progress_meter();
@@ -777,10 +835,10 @@ bwlimit(int amount)
thresh /= 2;
if (thresh < 2048)
thresh = 2048;
- } else if (bwend.tv_usec < 100) {
+ } else if (bwend.tv_usec < 10000) {
thresh *= 2;
- if (thresh > 32768)
- thresh = 32768;
+ if (thresh > COPY_BUFLEN * 4)
+ thresh = COPY_BUFLEN * 4;
}
TIMEVAL_TO_TIMESPEC(&bwend, &ts);
@@ -971,7 +1029,7 @@ bad: run_err("%s: %s", np, strerror(errno));
continue;
}
(void) atomicio(vwrite, remout, "", 1);
- if ((bp = allocbuf(&buffer, ofd, 4096)) == NULL) {
+ if ((bp = allocbuf(&buffer, ofd, COPY_BUFLEN)) == NULL) {
(void) close(ofd);
continue;
}
@@ -981,26 +1039,24 @@ bad: run_err("%s: %s", np, strerror(errno));
statbytes = 0;
if (showprogress)
start_progress_meter(curfile, size, &statbytes);
- for (count = i = 0; i < size; i += 4096) {
- amt = 4096;
+ set_nonblock(remin);
+ for (count = i = 0; i < size; i += bp->cnt) {
+ amt = bp->cnt;
if (i + amt > size)
amt = size - i;
count += amt;
do {
- j = atomicio(read, remin, cp, amt);
+ j = scpio(read, remin, cp, amt, &statbytes);
if (j == 0) {
- run_err("%s", j ? strerror(errno) :
+ run_err("%s", j != EPIPE ?
+ strerror(errno) :
"dropped connection");
exit(1);
}
amt -= j;
cp += j;
- statbytes += j;
} while (amt > 0);
- if (limit_rate)
- bwlimit(4096);
-
if (count == bp->cnt) {
/* Keep reading so we stay sync'd up. */
if (wrerr == NO) {
@@ -1014,6 +1070,7 @@ bad: run_err("%s: %s", np, strerror(errno));
cp = bp->buf;
}
}
+ unset_nonblock(remin);
if (showprogress)
stop_progress_meter();
if (count != 0 && wrerr == NO &&
@@ -1021,7 +1078,8 @@ bad: run_err("%s: %s", np, strerror(errno));
wrerr = YES;
wrerrno = errno;
}
- if (wrerr == NO && ftruncate(ofd, size) != 0) {
+ if (wrerr == NO && (!exists || S_ISREG(stb.st_mode)) &&
+ ftruncate(ofd, size) != 0) {
run_err("%s: truncate: %s", np, strerror(errno));
wrerr = DISPLAYED;
}
@@ -1116,7 +1174,7 @@ usage(void)
(void) fprintf(stderr,
"usage: scp [-1246BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]\n"
" [-l limit] [-o ssh_option] [-P port] [-S program]\n"
- " [[user@]host1:]file1 [...] [[user@]host2:]file2\n");
+ " [[user@]host1:]file1 ... [[user@]host2:]file2\n");
exit(1);
}
OpenPOWER on IntegriCloud