X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/aa2eae64b7a74e7293a673f5dc101189b5342668..d837615aa540e1d403bd3eaff7b62027cb3097f6:/scp.c diff --git a/scp.c b/scp.c index 4521f634..1765a44e 100644 --- a/scp.c +++ b/scp.c @@ -1,3 +1,4 @@ +/* $OpenBSD: scp.c,v 1.160 2007/08/06 19:16:06 sobrado Exp $ */ /* * scp - secure remote copy. This is basically patched BSD rcp which * uses ssh to do the data transfer (instead of using rcmd). @@ -71,12 +72,33 @@ */ #include "includes.h" -RCSID("$OpenBSD: scp.c,v 1.132 2006/02/10 01:44:26 stevesk Exp $"); #include +#include +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef HAVE_SYS_TIME_H +# include +#endif #include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) +#include +#endif #include "xmalloc.h" #include "atomicio.h" @@ -87,6 +109,8 @@ RCSID("$OpenBSD: scp.c,v 1.132 2006/02/10 01:44:26 stevesk Exp $"); extern char *__progname; +int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout); + void bwlimit(int); /* Struct for addargs */ @@ -172,7 +196,7 @@ do_local_cmd(arglist *a) */ int -do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc) +do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout) { int pin[2], pout[2], reserved[2]; @@ -186,7 +210,8 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc) * Reserve two descriptors so that the real pipes won't get * descriptors 0 and 1 because that will screw up dup2 below. */ - pipe(reserved); + if (pipe(reserved) < 0) + fatal("pipe: %s", strerror(errno)); /* Create a socket pair for communicating with ssh. */ if (pipe(pin) < 0) @@ -239,7 +264,6 @@ typedef struct { BUF *allocbuf(BUF *, int, int); void lostconn(int); -void nospace(void); int okname(char *); void run_err(const char *,...); void verifydir(char *); @@ -263,15 +287,21 @@ void usage(void); int main(int argc, char **argv) { - int ch, fflag, tflag, status; + int ch, fflag, tflag, status, n; double speed; - char *targ, *endp; + char *targ, *endp, **newargv; extern char *optarg; extern int optind; /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); + /* Copy argv, because we modify it */ + newargv = xcalloc(MAX(argc + 1, 1), sizeof(*newargv)); + for (n = 0; n < argc; n++) + newargv[n] = xstrdup(argv[n]); + argv = newargv; + __progname = ssh_get_progname(argv[0]); memset(&args, '\0', sizeof(args)); @@ -353,7 +383,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; @@ -414,9 +444,9 @@ main(int argc, char **argv) void toremote(char *targ, int argc, char **argv) { - int i, len; char *bp, *host, *src, *suser, *thost, *tuser, *arg; arglist alist; + int i; memset(&alist, '\0', sizeof(alist)); alist.list = NULL; @@ -481,12 +511,10 @@ toremote(char *targ, int argc, char **argv) errs = 1; } else { /* local to remote */ if (remin == -1) { - len = strlen(targ) + CMDNEEDS + 20; - bp = xmalloc(len); - (void) snprintf(bp, len, "%s -t %s", cmd, targ); + xasprintf(&bp, "%s -t %s", cmd, targ); host = cleanhostname(thost); if (do_cmd(host, tuser, bp, &remin, - &remout, argc) < 0) + &remout) < 0) exit(1); if (response() < 0) exit(1); @@ -495,14 +523,15 @@ toremote(char *targ, int argc, char **argv) source(1, argv + i); } } + xfree(arg); } void tolocal(int argc, char **argv) { - int i, len; char *bp, *host, *src, *suser; arglist alist; + int i; memset(&alist, '\0', sizeof(alist)); alist.list = NULL; @@ -534,10 +563,8 @@ tolocal(int argc, char **argv) suser = pwd->pw_name; } host = cleanhostname(host); - len = strlen(src) + CMDNEEDS + 20; - bp = xmalloc(len); - (void) snprintf(bp, len, "%s -f %s", cmd, src); - if (do_cmd(host, suser, bp, &remin, &remout, argc) < 0) { + xasprintf(&bp, "%s -f %s", cmd, src); + if (do_cmd(host, suser, bp, &remin, &remout) < 0) { (void) xfree(bp); ++errs; continue; @@ -558,7 +585,7 @@ source(int argc, char **argv) off_t i, amt, statbytes; size_t result; 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) { @@ -567,17 +594,17 @@ 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; } + unset_nonblock(fd); switch (stb.st_mode & S_IFMT) { case S_IFREG: break; @@ -782,7 +809,8 @@ sink(int argc, char **argv) BUF *bp; off_t i; size_t j, count; - int amt, exists, first, mask, mode, ofd, omode; + int amt, exists, first, ofd; + mode_t mode, omode, mask; off_t size, statbytes; int setimes, targisdir, wrerrno = 0; char ch, *cp, *np, *targ, *why, *vect[1], buf[2048]; @@ -996,7 +1024,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; } @@ -1091,7 +1120,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); } @@ -1102,15 +1131,15 @@ run_err(const char *fmt,...) va_list ap; ++errs; - if (fp == NULL && !(fp = fdopen(remout, "w"))) - return; - (void) fprintf(fp, "%c", 0x01); - (void) fprintf(fp, "scp: "); - va_start(ap, fmt); - (void) vfprintf(fp, fmt, ap); - va_end(ap); - (void) fprintf(fp, "\n"); - (void) fflush(fp); + if (fp != NULL || (remout != -1 && (fp = fdopen(remout, "w")))) { + (void) fprintf(fp, "%c", 0x01); + (void) fprintf(fp, "scp: "); + va_start(ap, fmt); + (void) vfprintf(fp, fmt, ap); + va_end(ap); + (void) fprintf(fp, "\n"); + (void) fflush(fp); + } if (!iamremote) { va_start(ap, fmt); @@ -1186,7 +1215,7 @@ allocbuf(BUF *bp, int fd, int blksize) if (bp->buf == NULL) bp->buf = xmalloc(size); else - bp->buf = xrealloc(bp->buf, size); + bp->buf = xrealloc(bp->buf, 1, size); memset(bp->buf, 0, size); bp->cnt = size; return (bp);