version 1.227, 2021/08/09 23:47:44 |
version 1.228, 2021/08/09 23:49:31 |
|
|
void toremote(int, char *[], enum scp_mode_e, char *sftp_direct); |
void toremote(int, char *[], enum scp_mode_e, char *sftp_direct); |
void usage(void); |
void usage(void); |
|
|
void source_sftp(int, char *, char *, struct sftp_conn *, char **); |
void source_sftp(int, char *, char *, struct sftp_conn *); |
void sink_sftp(int, char *, const char *, struct sftp_conn *); |
void sink_sftp(int, char *, const char *, struct sftp_conn *); |
void throughlocal_sftp(struct sftp_conn *, struct sftp_conn *, |
void throughlocal_sftp(struct sftp_conn *, struct sftp_conn *, |
char *, char *, char **); |
char *, char *); |
|
|
int |
int |
main(int argc, char **argv) |
main(int argc, char **argv) |
|
|
{ |
{ |
char *suser = NULL, *host = NULL, *src = NULL; |
char *suser = NULL, *host = NULL, *src = NULL; |
char *bp, *tuser, *thost, *targ; |
char *bp, *tuser, *thost, *targ; |
char *remote_path = NULL; |
|
int sport = -1, tport = -1; |
int sport = -1, tport = -1; |
struct sftp_conn *conn = NULL, *conn2 = NULL; |
struct sftp_conn *conn = NULL, *conn2 = NULL; |
arglist alist; |
arglist alist; |
|
|
} |
} |
debug3_f("destination in %d out %d pid %ld", |
debug3_f("destination in %d out %d pid %ld", |
remin2, remout2, (long)do_cmd_pid2); |
remin2, remout2, (long)do_cmd_pid2); |
throughlocal_sftp(conn2, conn, src, targ, |
throughlocal_sftp(conn2, conn, src, targ); |
&remote_path); |
|
(void) close(remin2); |
(void) close(remin2); |
(void) close(remout2); |
(void) close(remout2); |
remin2 = remout2 = -1; |
remin2 = remout2 = -1; |
|
|
} |
} |
|
|
/* The protocol */ |
/* The protocol */ |
source_sftp(1, argv[i], targ, conn, |
source_sftp(1, argv[i], targ, conn); |
&remote_path); |
|
continue; |
continue; |
} |
} |
/* SCP */ |
/* SCP */ |
|
|
} |
} |
} |
} |
out: |
out: |
if (mode == MODE_SFTP) { |
if (mode == MODE_SFTP) |
free(remote_path); |
|
free(conn); |
free(conn); |
} |
|
free(tuser); |
free(tuser); |
free(thost); |
free(thost); |
free(targ); |
free(targ); |
|
|
free(src); |
free(src); |
} |
} |
|
|
/* Canonicalise a remote path, handling ~ by assuming cwd is the homedir */ |
/* Prepare remote path, handling ~ by assuming cwd is the homedir */ |
static char * |
static char * |
absolute_remote_path(struct sftp_conn *conn, const char *path, |
prepare_remote_path(struct sftp_conn *conn, const char *path) |
const char *remote_path) |
|
{ |
{ |
char *ret; |
|
|
|
if (can_expand_path(conn)) |
|
return do_expand_path(conn, path); |
|
|
|
/* Handle ~ prefixed paths */ |
/* Handle ~ prefixed paths */ |
if (*path != '~') |
if (*path != '~') |
ret = xstrdup(path); |
return xstrdup(path); |
else { |
if (*path == '\0' || strcmp(path, "~") == 0) |
if (strcmp(path, "~") == 0) |
return xstrdup("."); |
ret = xstrdup(""); |
if (strncmp(path, "~/", 2) == 0) |
else if (strncmp(path, "~/", 2) == 0) |
return xstrdup(path + 2); |
ret = xstrdup(path + 2); |
if (can_expand_path(conn)) |
else { |
return do_expand_path(conn, path); |
/* XXX could be supported with protocol extension */ |
/* No protocol extension */ |
error("~user paths are not currently supported"); |
error("~user paths are not currently supported"); |
return NULL; |
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) |
struct sftp_conn *conn, char **remote_path) |
|
{ |
{ |
char *target = NULL, *filename = NULL, *abs_dst = NULL; |
char *target = NULL, *filename = NULL, *abs_dst = NULL; |
int target_is_dir; |
int target_is_dir; |
|
|
if (*remote_path == NULL) { |
|
*remote_path = do_realpath(conn, "."); |
|
if (*remote_path == NULL) |
|
fatal("Unable to determine remote working directory"); |
|
} |
|
|
|
if ((filename = basename(src)) == NULL) |
if ((filename = basename(src)) == NULL) |
fatal("basename %s: %s", src, strerror(errno)); |
fatal("basename %s: %s", src, strerror(errno)); |
|
|
|
|
* 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 |
*/ |
*/ |
if ((target = absolute_remote_path(conn, targ, *remote_path)) == NULL) |
if ((target = prepare_remote_path(conn, targ)) == NULL) |
cleanup_exit(255); |
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) { |
|
|
char *abs_src = NULL; |
char *abs_src = NULL; |
char *abs_dst = NULL; |
char *abs_dst = NULL; |
glob_t g; |
glob_t g; |
char *filename, *tmp = NULL, *remote_path = NULL; |
char *filename, *tmp = NULL; |
int i, r, err = 0; |
int i, r, err = 0; |
|
|
memset(&g, 0, sizeof(g)); |
memset(&g, 0, sizeof(g)); |
|
|
* expansions |
* expansions |
*/ |
*/ |
|
|
remote_path = do_realpath(conn, "."); |
if ((abs_src = prepare_remote_path(conn, src)) == NULL) { |
if (remote_path == NULL) { |
|
error("Could not obtain remote working directory"); |
|
/* TODO - gracefully degrade by using relative paths ? */ |
|
err = -1; |
err = -1; |
goto out; |
goto out; |
} |
} |
|
|
if ((abs_src = absolute_remote_path(conn, src, remote_path)) == NULL) { |
|
err = -1; |
|
goto out; |
|
} |
|
free(remote_path); |
|
|
|
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 (r == GLOB_NOSPACE) |
if (r == GLOB_NOSPACE) |
|
|
|
|
void |
void |
throughlocal_sftp(struct sftp_conn *from, struct sftp_conn *to, |
throughlocal_sftp(struct sftp_conn *from, struct sftp_conn *to, |
char *src, char *targ, char **to_remote_path) |
char *src, char *targ) |
{ |
{ |
char *target = NULL, *filename = NULL, *abs_dst = NULL; |
char *target = NULL, *filename = NULL, *abs_dst = NULL; |
char *abs_src = NULL, *tmp = NULL, *from_remote_path; |
char *abs_src = NULL, *tmp = NULL; |
glob_t g; |
glob_t g; |
int i, r, targetisdir, err = 0; |
int i, r, targetisdir, err = 0; |
|
|
if (*to_remote_path == NULL) { |
|
*to_remote_path = do_realpath(to, "."); |
|
if (*to_remote_path == NULL) { |
|
fatal("Unable to determine destination remote " |
|
"working directory"); |
|
} |
|
} |
|
|
|
if ((from_remote_path = do_realpath(from, ".")) == NULL) { |
|
fatal("Unable to determine source remote " |
|
"working directory"); |
|
} |
|
|
|
if ((filename = basename(src)) == NULL) |
if ((filename = basename(src)) == NULL) |
fatal("basename %s: %s", src, strerror(errno)); |
fatal("basename %s: %s", src, strerror(errno)); |
|
|
if ((abs_src = absolute_remote_path(from, src, |
if ((abs_src = prepare_remote_path(from, src)) == NULL || |
from_remote_path)) == NULL || |
(target = prepare_remote_path(to, targ)) == NULL) |
(target = absolute_remote_path(to, targ, *to_remote_path)) == NULL) |
|
cleanup_exit(255); |
cleanup_exit(255); |
free(from_remote_path); |
|
memset(&g, 0, sizeof(g)); |
memset(&g, 0, sizeof(g)); |
|
|
targetisdir = remote_is_dir(to, target); |
targetisdir = remote_is_dir(to, target); |