version 1.222, 2021/08/07 01:57:08 |
version 1.223, 2021/08/09 07:13:54 |
|
|
* This is set to non-zero if remote-remote copy should be piped |
* This is set to non-zero if remote-remote copy should be piped |
* through this process. |
* through this process. |
*/ |
*/ |
int throughlocal = 0; |
int throughlocal = 1; |
|
|
/* Non-standard port to use for the ssh connection or -1. */ |
/* Non-standard port to use for the ssh connection or -1. */ |
int sshport = -1; |
int sshport = -1; |
|
|
const char *errstr; |
const char *errstr; |
extern char *optarg; |
extern char *optarg; |
extern int optind; |
extern int optind; |
/* For now, keep SCP as default */ |
enum scp_mode_e mode = MODE_SFTP; |
enum scp_mode_e mode = MODE_SCP; |
|
char *sftp_direct = NULL; |
char *sftp_direct = NULL; |
|
|
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ |
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ |
|
|
|
|
fflag = Tflag = tflag = 0; |
fflag = Tflag = tflag = 0; |
while ((ch = getopt(argc, argv, |
while ((ch = getopt(argc, argv, |
"12346ABCTdfpqrtvD:F:J:M:P:S:c:i:l:o:")) != -1) { |
"12346ABCORTdfpqrtvD:F:J:P:S:c:i:l:o:")) != -1) { |
switch (ch) { |
switch (ch) { |
/* User-visible flags. */ |
/* User-visible flags. */ |
case '1': |
case '1': |
|
|
case '3': |
case '3': |
throughlocal = 1; |
throughlocal = 1; |
break; |
break; |
|
case 'R': |
|
throughlocal = 0; |
|
break; |
case 'o': |
case 'o': |
case 'c': |
case 'c': |
case 'i': |
case 'i': |
|
|
addargs(&args, "-%c", ch); |
addargs(&args, "-%c", ch); |
addargs(&args, "%s", optarg); |
addargs(&args, "%s", optarg); |
break; |
break; |
|
case 'O': |
|
mode = MODE_SCP; |
|
break; |
case 'P': |
case 'P': |
sshport = a2port(optarg); |
sshport = a2port(optarg); |
if (sshport <= 0) |
if (sshport <= 0) |
|
|
addargs(&remote_remote_args, "-oBatchmode=yes"); |
addargs(&remote_remote_args, "-oBatchmode=yes"); |
addargs(&args, "-oBatchmode=yes"); |
addargs(&args, "-oBatchmode=yes"); |
break; |
break; |
case 'M': |
|
if (strcmp(optarg, "sftp") == 0) |
|
mode = MODE_SFTP; |
|
else if (strcmp(optarg, "scp") == 0) |
|
mode = MODE_SCP; |
|
else |
|
usage(); |
|
break; |
|
case 'l': |
case 'l': |
limit_kbps = strtonum(optarg, 1, 100 * 1024 * 1024, |
limit_kbps = strtonum(optarg, 1, 100 * 1024 * 1024, |
&errstr); |
&errstr); |
|
|
free(src); |
free(src); |
} |
} |
|
|
|
/* Canonicalise a remote path, handling ~ by assuming cwd is the homedir */ |
|
static char * |
|
absolute_remote_path(const char *path, const char *remote_path) |
|
{ |
|
char *ret; |
|
|
|
/* Handle ~ prefixed paths */ |
|
if (*path != '~') |
|
ret = xstrdup(path); |
|
else { |
|
if (strcmp(path, "~") == 0) |
|
ret = xstrdup(""); |
|
else if (strncmp(path, "~/", 2) == 0) |
|
ret = xstrdup(path + 2); |
|
else { |
|
/* XXX could be supported with protocol extension */ |
|
error("~user paths are not currently supported"); |
|
return NULL; |
|
} |
|
} |
|
return make_absolute(ret, remote_path); |
|
} |
|
|
void |
void |
source_sftp(int argc, char *src, char *targ, |
source_sftp(int argc, char *src, char *targ, |
struct sftp_conn *conn, char **remote_path) |
struct sftp_conn *conn, char **remote_path) |
|
|
* No need to glob here - the local shell already took care of |
* No need to glob here - the local shell already took care of |
* the expansions |
* the expansions |
*/ |
*/ |
target = xstrdup(targ); |
if ((target = absolute_remote_path(targ, *remote_path)) == NULL) |
target = make_absolute(target, *remote_path); |
cleanup_exit(255); |
target_is_dir = remote_is_dir(conn, target); |
target_is_dir = remote_is_dir(conn, target); |
if (targetshouldbedirectory && !target_is_dir) { |
if (targetshouldbedirectory && !target_is_dir) { |
fatal("Target is not a directory, but more files selected " |
fatal("Target is not a directory, but more files selected " |
|
|
char *filename, *tmp = NULL, *remote_path = NULL; |
char *filename, *tmp = NULL, *remote_path = NULL; |
int i, r, err = 0; |
int i, r, err = 0; |
|
|
|
memset(&g, 0, sizeof(g)); |
/* |
/* |
* Here, we need remote glob as SFTP can not depend on remote shell |
* Here, we need remote glob as SFTP can not depend on remote shell |
* expansions |
* expansions |
|
|
goto out; |
goto out; |
} |
} |
|
|
abs_src = xstrdup(src); |
if ((abs_src = absolute_remote_path(src, remote_path)) == NULL) { |
abs_src = make_absolute(abs_src, remote_path); |
err = -1; |
|
goto out; |
|
} |
free(remote_path); |
free(remote_path); |
memset(&g, 0, sizeof(g)); |
|
|
|
debug3_f("copying remote %s to local %s", abs_src, dst); |
debug3_f("copying remote %s to local %s", abs_src, dst); |
if ((r = remote_glob(conn, abs_src, GLOB_MARK, NULL, &g)) != 0) { |
if ((r = remote_glob(conn, abs_src, GLOB_MARK, NULL, &g)) != 0) { |
|
|
if ((filename = basename(src)) == NULL) |
if ((filename = basename(src)) == NULL) |
fatal("basename %s: %s", src, strerror(errno)); |
fatal("basename %s: %s", src, strerror(errno)); |
|
|
abs_src = xstrdup(src); |
if ((abs_src = absolute_remote_path(src, from_remote_path)) == NULL || |
abs_src = make_absolute(abs_src, from_remote_path); |
(target = absolute_remote_path(targ, *to_remote_path)) == NULL) |
|
cleanup_exit(255); |
free(from_remote_path); |
free(from_remote_path); |
target = xstrdup(targ); |
|
target = make_absolute(target, *to_remote_path); |
|
memset(&g, 0, sizeof(g)); |
memset(&g, 0, sizeof(g)); |
|
|
targetisdir = remote_is_dir(to, target); |
targetisdir = remote_is_dir(to, target); |
|
|
usage(void) |
usage(void) |
{ |
{ |
(void) fprintf(stderr, |
(void) fprintf(stderr, |
"usage: scp [-346ABCpqrTv] [-c cipher] [-D sftp_server_path] [-F ssh_config]\n" |
"usage: scp [-346ABCOpqrTv] [-c cipher] [-D sftp_server_path] [-F ssh_config]\n" |
" [-i identity_file] [-J destination] [-l limit] [-M scp|sftp]\n" |
" [-i identity_file] [-J destination] [-l limit] [-o ssh_option]\n" |
" [-o ssh_option] [-P port] [-S program] source ... target\n"); |
" [-P port] [-S program] source ... target\n"); |
exit(1); |
exit(1); |
} |
} |
|
|
|
|
_exit(1); |
_exit(1); |
else |
else |
exit(1); |
exit(1); |
|
} |
|
|
|
void |
|
cleanup_exit(int i) |
|
{ |
|
if (remin > 0) |
|
close(remin); |
|
if (remout > 0) |
|
close(remout); |
|
if (remin2 > 0) |
|
close(remin2); |
|
if (remout2 > 0) |
|
close(remout2); |
|
if (do_cmd_pid > 0) |
|
waitpid(do_cmd_pid, NULL, 0); |
|
if (do_cmd_pid2 > 0) |
|
waitpid(do_cmd_pid2, NULL, 0); |
|
exit(i); |
} |
} |