upstream: the sftp code was one of my first contributions to
OpenSSH and it shows - the function names are terrible. Rename do_blah() to sftp_blah() to make them less so. Completely mechanical except for sftp_stat() and sftp_lstat() which change from returning a pointer to a static variable (error-prone) to taking a pointer to a caller-provided receiver. OpenBSD-Commit-ID: eb54d6a72d0bbba4d623e2175cf5cc4c75dc2ba4
This commit is contained in:
parent
249d8bd047
commit
2de990142a
44
scp.c
44
scp.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: scp.c,v 1.257 2023/07/14 05:31:44 djm Exp $ */
|
/* $OpenBSD: scp.c,v 1.258 2023/09/08 05:56:13 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* scp - secure remote copy. This is basically patched BSD rcp which
|
* scp - secure remote copy. This is basically patched BSD rcp which
|
||||||
* uses ssh to do the data transfer (instead of using rcmd).
|
* uses ssh to do the data transfer (instead of using rcmd).
|
||||||
|
@ -1028,7 +1028,7 @@ do_sftp_connect(char *host, char *user, int port, char *sftp_direct,
|
||||||
reminp, remoutp, pidp) < 0)
|
reminp, remoutp, pidp) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return do_init(*reminp, *remoutp,
|
return sftp_init(*reminp, *remoutp,
|
||||||
sftp_copy_buflen, sftp_nrequests, limit_kbps);
|
sftp_copy_buflen, sftp_nrequests, limit_kbps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1324,8 +1324,8 @@ prepare_remote_path(struct sftp_conn *conn, const char *path)
|
||||||
return xstrdup(".");
|
return xstrdup(".");
|
||||||
return xstrdup(path + 2 + nslash);
|
return xstrdup(path + 2 + nslash);
|
||||||
}
|
}
|
||||||
if (can_expand_path(conn))
|
if (sftp_can_expand_path(conn))
|
||||||
return do_expand_path(conn, path);
|
return sftp_expand_path(conn, path);
|
||||||
/* No protocol extension */
|
/* No protocol extension */
|
||||||
error("server expand-path extension is required "
|
error("server expand-path extension is required "
|
||||||
"for ~user paths in SFTP mode");
|
"for ~user paths in SFTP mode");
|
||||||
|
@ -1353,17 +1353,17 @@ source_sftp(int argc, char *src, char *targ, struct sftp_conn *conn)
|
||||||
*/
|
*/
|
||||||
if ((target = prepare_remote_path(conn, targ)) == 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 = sftp_remote_is_dir(conn, target);
|
||||||
if (targetshouldbedirectory && !target_is_dir) {
|
if (targetshouldbedirectory && !target_is_dir) {
|
||||||
debug("target directory \"%s\" does not exist", target);
|
debug("target directory \"%s\" does not exist", target);
|
||||||
a.flags = SSH2_FILEXFER_ATTR_PERMISSIONS;
|
a.flags = SSH2_FILEXFER_ATTR_PERMISSIONS;
|
||||||
a.perm = st.st_mode | 0700; /* ensure writable */
|
a.perm = st.st_mode | 0700; /* ensure writable */
|
||||||
if (do_mkdir(conn, target, &a, 1) != 0)
|
if (sftp_mkdir(conn, target, &a, 1) != 0)
|
||||||
cleanup_exit(255); /* error already logged */
|
cleanup_exit(255); /* error already logged */
|
||||||
target_is_dir = 1;
|
target_is_dir = 1;
|
||||||
}
|
}
|
||||||
if (target_is_dir)
|
if (target_is_dir)
|
||||||
abs_dst = path_append(target, filename);
|
abs_dst = sftp_path_append(target, filename);
|
||||||
else {
|
else {
|
||||||
abs_dst = target;
|
abs_dst = target;
|
||||||
target = NULL;
|
target = NULL;
|
||||||
|
@ -1371,12 +1371,12 @@ source_sftp(int argc, char *src, char *targ, struct sftp_conn *conn)
|
||||||
debug3_f("copying local %s to remote %s", src, abs_dst);
|
debug3_f("copying local %s to remote %s", src, abs_dst);
|
||||||
|
|
||||||
if (src_is_dir && iamrecursive) {
|
if (src_is_dir && iamrecursive) {
|
||||||
if (upload_dir(conn, src, abs_dst, pflag,
|
if (sftp_upload_dir(conn, src, abs_dst, pflag,
|
||||||
SFTP_PROGRESS_ONLY, 0, 0, 1, 1) != 0) {
|
SFTP_PROGRESS_ONLY, 0, 0, 1, 1) != 0) {
|
||||||
error("failed to upload directory %s to %s", src, targ);
|
error("failed to upload directory %s to %s", src, targ);
|
||||||
errs = 1;
|
errs = 1;
|
||||||
}
|
}
|
||||||
} else if (do_upload(conn, src, abs_dst, pflag, 0, 0, 1) != 0) {
|
} else if (sftp_upload(conn, src, abs_dst, pflag, 0, 0, 1) != 0) {
|
||||||
error("failed to upload file %s to %s", src, targ);
|
error("failed to upload file %s to %s", src, targ);
|
||||||
errs = 1;
|
errs = 1;
|
||||||
}
|
}
|
||||||
|
@ -1585,7 +1585,7 @@ sink_sftp(int argc, char *dst, const char *src, struct sftp_conn *conn)
|
||||||
* a GLOB_NOCHECK result. Check whether the unglobbed path
|
* a GLOB_NOCHECK result. Check whether the unglobbed path
|
||||||
* exists so we can give a nice error message early.
|
* exists so we can give a nice error message early.
|
||||||
*/
|
*/
|
||||||
if (do_stat(conn, g.gl_pathv[0], 1) == NULL) {
|
if (sftp_stat(conn, g.gl_pathv[0], 1, NULL) != 0) {
|
||||||
error("%s: %s", src, strerror(ENOENT));
|
error("%s: %s", src, strerror(ENOENT));
|
||||||
err = -1;
|
err = -1;
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -1621,17 +1621,17 @@ sink_sftp(int argc, char *dst, const char *src, struct sftp_conn *conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dst_is_dir)
|
if (dst_is_dir)
|
||||||
abs_dst = path_append(dst, filename);
|
abs_dst = sftp_path_append(dst, filename);
|
||||||
else
|
else
|
||||||
abs_dst = xstrdup(dst);
|
abs_dst = xstrdup(dst);
|
||||||
|
|
||||||
debug("Fetching %s to %s\n", g.gl_pathv[i], abs_dst);
|
debug("Fetching %s to %s\n", g.gl_pathv[i], abs_dst);
|
||||||
if (globpath_is_dir(g.gl_pathv[i]) && iamrecursive) {
|
if (sftp_globpath_is_dir(g.gl_pathv[i]) && iamrecursive) {
|
||||||
if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL,
|
if (sftp_download_dir(conn, g.gl_pathv[i], abs_dst,
|
||||||
pflag, SFTP_PROGRESS_ONLY, 0, 0, 1, 1) == -1)
|
NULL, pflag, SFTP_PROGRESS_ONLY, 0, 0, 1, 1) == -1)
|
||||||
err = -1;
|
err = -1;
|
||||||
} else {
|
} else {
|
||||||
if (do_download(conn, g.gl_pathv[i], abs_dst, NULL,
|
if (sftp_download(conn, g.gl_pathv[i], abs_dst, NULL,
|
||||||
pflag, 0, 0, 1) == -1)
|
pflag, 0, 0, 1) == -1)
|
||||||
err = -1;
|
err = -1;
|
||||||
}
|
}
|
||||||
|
@ -1993,7 +1993,7 @@ throughlocal_sftp(struct sftp_conn *from, struct sftp_conn *to,
|
||||||
cleanup_exit(255);
|
cleanup_exit(255);
|
||||||
memset(&g, 0, sizeof(g));
|
memset(&g, 0, sizeof(g));
|
||||||
|
|
||||||
targetisdir = remote_is_dir(to, target);
|
targetisdir = sftp_remote_is_dir(to, target);
|
||||||
if (!targetisdir && targetshouldbedirectory) {
|
if (!targetisdir && targetshouldbedirectory) {
|
||||||
error("%s: destination is not a directory", targ);
|
error("%s: destination is not a directory", targ);
|
||||||
err = -1;
|
err = -1;
|
||||||
|
@ -2018,7 +2018,7 @@ throughlocal_sftp(struct sftp_conn *from, struct sftp_conn *to,
|
||||||
* a GLOB_NOCHECK result. Check whether the unglobbed path
|
* a GLOB_NOCHECK result. Check whether the unglobbed path
|
||||||
* exists so we can give a nice error message early.
|
* exists so we can give a nice error message early.
|
||||||
*/
|
*/
|
||||||
if (do_stat(from, g.gl_pathv[0], 1) == NULL) {
|
if (sftp_stat(from, g.gl_pathv[0], 1, NULL) != 0) {
|
||||||
error("%s: %s", src, strerror(ENOENT));
|
error("%s: %s", src, strerror(ENOENT));
|
||||||
err = -1;
|
err = -1;
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -2034,18 +2034,18 @@ throughlocal_sftp(struct sftp_conn *from, struct sftp_conn *to,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetisdir)
|
if (targetisdir)
|
||||||
abs_dst = path_append(target, filename);
|
abs_dst = sftp_path_append(target, filename);
|
||||||
else
|
else
|
||||||
abs_dst = xstrdup(target);
|
abs_dst = xstrdup(target);
|
||||||
|
|
||||||
debug("Fetching %s to %s\n", g.gl_pathv[i], abs_dst);
|
debug("Fetching %s to %s\n", g.gl_pathv[i], abs_dst);
|
||||||
if (globpath_is_dir(g.gl_pathv[i]) && iamrecursive) {
|
if (sftp_globpath_is_dir(g.gl_pathv[i]) && iamrecursive) {
|
||||||
if (crossload_dir(from, to, g.gl_pathv[i], abs_dst,
|
if (sftp_crossload_dir(from, to, g.gl_pathv[i], abs_dst,
|
||||||
NULL, pflag, SFTP_PROGRESS_ONLY, 1) == -1)
|
NULL, pflag, SFTP_PROGRESS_ONLY, 1) == -1)
|
||||||
err = -1;
|
err = -1;
|
||||||
} else {
|
} else {
|
||||||
if (do_crossload(from, to, g.gl_pathv[i], abs_dst, NULL,
|
if (sftp_crossload(from, to, g.gl_pathv[i], abs_dst,
|
||||||
pflag) == -1)
|
NULL, pflag) == -1)
|
||||||
err = -1;
|
err = -1;
|
||||||
}
|
}
|
||||||
free(abs_dst);
|
free(abs_dst);
|
||||||
|
|
316
sftp-client.c
316
sftp-client.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: sftp-client.c,v 1.172 2023/09/08 05:50:12 djm Exp $ */
|
/* $OpenBSD: sftp-client.c,v 1.173 2023/09/08 05:56:13 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
|
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
|
||||||
*
|
*
|
||||||
|
@ -342,16 +342,17 @@ get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len,
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX returning &static is error-prone. Refactor to fill *Attrib argument */
|
static int
|
||||||
static Attrib *
|
get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet, Attrib *a)
|
||||||
get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet)
|
|
||||||
{
|
{
|
||||||
struct sshbuf *msg;
|
struct sshbuf *msg;
|
||||||
u_int id;
|
u_int id;
|
||||||
u_char type;
|
u_char type;
|
||||||
int r;
|
int r;
|
||||||
static Attrib a;
|
Attrib attr;
|
||||||
|
|
||||||
|
if (a != NULL)
|
||||||
|
memset(a, '\0', sizeof(*a));
|
||||||
if ((msg = sshbuf_new()) == NULL)
|
if ((msg = sshbuf_new()) == NULL)
|
||||||
fatal_f("sshbuf_new failed");
|
fatal_f("sshbuf_new failed");
|
||||||
get_msg(conn, msg);
|
get_msg(conn, msg);
|
||||||
|
@ -372,21 +373,24 @@ get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet)
|
||||||
else
|
else
|
||||||
error("stat remote: %s", fx2txt(status));
|
error("stat remote: %s", fx2txt(status));
|
||||||
sshbuf_free(msg);
|
sshbuf_free(msg);
|
||||||
return(NULL);
|
return -1;
|
||||||
} else if (type != SSH2_FXP_ATTRS) {
|
} else if (type != SSH2_FXP_ATTRS) {
|
||||||
fatal("Expected SSH2_FXP_ATTRS(%u) packet, got %u",
|
fatal("Expected SSH2_FXP_ATTRS(%u) packet, got %u",
|
||||||
SSH2_FXP_ATTRS, type);
|
SSH2_FXP_ATTRS, type);
|
||||||
}
|
}
|
||||||
if ((r = decode_attrib(msg, &a)) != 0) {
|
if ((r = decode_attrib(msg, &attr)) != 0) {
|
||||||
error_fr(r, "decode_attrib");
|
error_fr(r, "decode_attrib");
|
||||||
sshbuf_free(msg);
|
sshbuf_free(msg);
|
||||||
return NULL;
|
return -1;
|
||||||
}
|
}
|
||||||
|
/* success */
|
||||||
|
if (a != NULL)
|
||||||
|
*a = attr;
|
||||||
debug3("Received stat reply T:%u I:%u F:0x%04x M:%05o",
|
debug3("Received stat reply T:%u I:%u F:0x%04x M:%05o",
|
||||||
type, id, a.flags, a.perm);
|
type, id, attr.flags, attr.perm);
|
||||||
sshbuf_free(msg);
|
sshbuf_free(msg);
|
||||||
|
|
||||||
return &a;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -449,7 +453,7 @@ get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sftp_conn *
|
struct sftp_conn *
|
||||||
do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests,
|
sftp_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests,
|
||||||
u_int64_t limit_kbps)
|
u_int64_t limit_kbps)
|
||||||
{
|
{
|
||||||
u_char type;
|
u_char type;
|
||||||
|
@ -560,7 +564,7 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests,
|
||||||
/* Query the server for its limits */
|
/* Query the server for its limits */
|
||||||
if (ret->exts & SFTP_EXT_LIMITS) {
|
if (ret->exts & SFTP_EXT_LIMITS) {
|
||||||
struct sftp_limits limits;
|
struct sftp_limits limits;
|
||||||
if (do_limits(ret, &limits) != 0)
|
if (sftp_get_limits(ret, &limits) != 0)
|
||||||
fatal_f("limits failed");
|
fatal_f("limits failed");
|
||||||
|
|
||||||
/* If the caller did not specify, find a good value */
|
/* If the caller did not specify, find a good value */
|
||||||
|
@ -614,7 +618,7 @@ sftp_proto_version(struct sftp_conn *conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
do_limits(struct sftp_conn *conn, struct sftp_limits *limits)
|
sftp_get_limits(struct sftp_conn *conn, struct sftp_limits *limits)
|
||||||
{
|
{
|
||||||
u_int id, msg_id;
|
u_int id, msg_id;
|
||||||
u_char type;
|
u_char type;
|
||||||
|
@ -668,7 +672,7 @@ do_limits(struct sftp_conn *conn, struct sftp_limits *limits)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
do_close(struct sftp_conn *conn, const u_char *handle, u_int handle_len)
|
sftp_close(struct sftp_conn *conn, const u_char *handle, u_int handle_len)
|
||||||
{
|
{
|
||||||
u_int id, status;
|
u_int id, status;
|
||||||
struct sshbuf *msg;
|
struct sshbuf *msg;
|
||||||
|
@ -696,7 +700,7 @@ do_close(struct sftp_conn *conn, const u_char *handle, u_int handle_len)
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag,
|
sftp_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag,
|
||||||
SFTP_DIRENT ***dir)
|
SFTP_DIRENT ***dir)
|
||||||
{
|
{
|
||||||
struct sshbuf *msg;
|
struct sshbuf *msg;
|
||||||
|
@ -821,16 +825,16 @@ do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag,
|
||||||
|
|
||||||
out:
|
out:
|
||||||
sshbuf_free(msg);
|
sshbuf_free(msg);
|
||||||
do_close(conn, handle, handle_len);
|
sftp_close(conn, handle, handle_len);
|
||||||
free(handle);
|
free(handle);
|
||||||
|
|
||||||
if (status != 0 && dir != NULL) {
|
if (status != 0 && dir != NULL) {
|
||||||
/* Don't return results on error */
|
/* Don't return results on error */
|
||||||
free_sftp_dirents(*dir);
|
sftp_free_dirents(*dir);
|
||||||
*dir = NULL;
|
*dir = NULL;
|
||||||
} else if (interrupted && dir != NULL && *dir != NULL) {
|
} else if (interrupted && dir != NULL && *dir != NULL) {
|
||||||
/* Don't return partial matches on interrupt */
|
/* Don't return partial matches on interrupt */
|
||||||
free_sftp_dirents(*dir);
|
sftp_free_dirents(*dir);
|
||||||
*dir = xcalloc(1, sizeof(**dir));
|
*dir = xcalloc(1, sizeof(**dir));
|
||||||
**dir = NULL;
|
**dir = NULL;
|
||||||
}
|
}
|
||||||
|
@ -839,12 +843,12 @@ do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag,
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
do_readdir(struct sftp_conn *conn, const char *path, SFTP_DIRENT ***dir)
|
sftp_readdir(struct sftp_conn *conn, const char *path, SFTP_DIRENT ***dir)
|
||||||
{
|
{
|
||||||
return(do_lsreaddir(conn, path, 0, dir));
|
return sftp_lsreaddir(conn, path, 0, dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_sftp_dirents(SFTP_DIRENT **s)
|
void sftp_free_dirents(SFTP_DIRENT **s)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -859,7 +863,7 @@ void free_sftp_dirents(SFTP_DIRENT **s)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
do_rm(struct sftp_conn *conn, const char *path)
|
sftp_rm(struct sftp_conn *conn, const char *path)
|
||||||
{
|
{
|
||||||
u_int status, id;
|
u_int status, id;
|
||||||
|
|
||||||
|
@ -874,7 +878,7 @@ do_rm(struct sftp_conn *conn, const char *path)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
do_mkdir(struct sftp_conn *conn, const char *path, Attrib *a, int print_flag)
|
sftp_mkdir(struct sftp_conn *conn, const char *path, Attrib *a, int print_flag)
|
||||||
{
|
{
|
||||||
u_int status, id;
|
u_int status, id;
|
||||||
|
|
||||||
|
@ -892,7 +896,7 @@ do_mkdir(struct sftp_conn *conn, const char *path, Attrib *a, int print_flag)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
do_rmdir(struct sftp_conn *conn, const char *path)
|
sftp_rmdir(struct sftp_conn *conn, const char *path)
|
||||||
{
|
{
|
||||||
u_int status, id;
|
u_int status, id;
|
||||||
|
|
||||||
|
@ -909,8 +913,8 @@ do_rmdir(struct sftp_conn *conn, const char *path)
|
||||||
return status == SSH2_FX_OK ? 0 : -1;
|
return status == SSH2_FX_OK ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Attrib *
|
int
|
||||||
do_stat(struct sftp_conn *conn, const char *path, int quiet)
|
sftp_stat(struct sftp_conn *conn, const char *path, int quiet, Attrib *a)
|
||||||
{
|
{
|
||||||
u_int id;
|
u_int id;
|
||||||
|
|
||||||
|
@ -922,33 +926,31 @@ do_stat(struct sftp_conn *conn, const char *path, int quiet)
|
||||||
conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT,
|
conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT,
|
||||||
path, strlen(path));
|
path, strlen(path));
|
||||||
|
|
||||||
return(get_decode_stat(conn, id, quiet));
|
return get_decode_stat(conn, id, quiet, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
Attrib *
|
int
|
||||||
do_lstat(struct sftp_conn *conn, const char *path, int quiet)
|
sftp_lstat(struct sftp_conn *conn, const char *path, int quiet, Attrib *a)
|
||||||
{
|
{
|
||||||
u_int id;
|
u_int id;
|
||||||
|
|
||||||
if (conn->version == 0) {
|
if (conn->version == 0) {
|
||||||
if (quiet)
|
do_log2(quiet ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_INFO,
|
||||||
debug("Server version does not support lstat operation");
|
"Server version does not support lstat operation");
|
||||||
else
|
return sftp_stat(conn, path, quiet, a);
|
||||||
logit("Server version does not support lstat operation");
|
|
||||||
return(do_stat(conn, path, quiet));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
id = conn->msg_id++;
|
id = conn->msg_id++;
|
||||||
send_string_request(conn, id, SSH2_FXP_LSTAT, path,
|
send_string_request(conn, id, SSH2_FXP_LSTAT, path,
|
||||||
strlen(path));
|
strlen(path));
|
||||||
|
|
||||||
return(get_decode_stat(conn, id, quiet));
|
return get_decode_stat(conn, id, quiet, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef notyet
|
#ifdef notyet
|
||||||
Attrib *
|
int
|
||||||
do_fstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
|
sftp_fstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
|
||||||
int quiet)
|
int quiet, Attrib *a)
|
||||||
{
|
{
|
||||||
u_int id;
|
u_int id;
|
||||||
|
|
||||||
|
@ -958,12 +960,12 @@ do_fstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
|
||||||
send_string_request(conn, id, SSH2_FXP_FSTAT, handle,
|
send_string_request(conn, id, SSH2_FXP_FSTAT, handle,
|
||||||
handle_len);
|
handle_len);
|
||||||
|
|
||||||
return(get_decode_stat(conn, id, quiet));
|
return get_decode_stat(conn, id, quiet, a);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int
|
int
|
||||||
do_setstat(struct sftp_conn *conn, const char *path, Attrib *a)
|
sftp_setstat(struct sftp_conn *conn, const char *path, Attrib *a)
|
||||||
{
|
{
|
||||||
u_int status, id;
|
u_int status, id;
|
||||||
|
|
||||||
|
@ -981,7 +983,7 @@ do_setstat(struct sftp_conn *conn, const char *path, Attrib *a)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
do_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
|
sftp_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
|
||||||
Attrib *a)
|
Attrib *a)
|
||||||
{
|
{
|
||||||
u_int status, id;
|
u_int status, id;
|
||||||
|
@ -1001,7 +1003,7 @@ do_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
|
||||||
|
|
||||||
/* Implements both the realpath and expand-path operations */
|
/* Implements both the realpath and expand-path operations */
|
||||||
static char *
|
static char *
|
||||||
do_realpath_expand(struct sftp_conn *conn, const char *path, int expand)
|
sftp_realpath_expand(struct sftp_conn *conn, const char *path, int expand)
|
||||||
{
|
{
|
||||||
struct sshbuf *msg;
|
struct sshbuf *msg;
|
||||||
u_int expected_id, count, id;
|
u_int expected_id, count, id;
|
||||||
|
@ -1076,31 +1078,31 @@ do_realpath_expand(struct sftp_conn *conn, const char *path, int expand)
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
do_realpath(struct sftp_conn *conn, const char *path)
|
sftp_realpath(struct sftp_conn *conn, const char *path)
|
||||||
{
|
{
|
||||||
return do_realpath_expand(conn, path, 0);
|
return sftp_realpath_expand(conn, path, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
can_expand_path(struct sftp_conn *conn)
|
sftp_can_expand_path(struct sftp_conn *conn)
|
||||||
{
|
{
|
||||||
return (conn->exts & SFTP_EXT_PATH_EXPAND) != 0;
|
return (conn->exts & SFTP_EXT_PATH_EXPAND) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
do_expand_path(struct sftp_conn *conn, const char *path)
|
sftp_expand_path(struct sftp_conn *conn, const char *path)
|
||||||
{
|
{
|
||||||
if (!can_expand_path(conn)) {
|
if (!sftp_can_expand_path(conn)) {
|
||||||
debug3_f("no server support, fallback to realpath");
|
debug3_f("no server support, fallback to realpath");
|
||||||
return do_realpath_expand(conn, path, 0);
|
return sftp_realpath_expand(conn, path, 0);
|
||||||
}
|
}
|
||||||
return do_realpath_expand(conn, path, 1);
|
return sftp_realpath_expand(conn, path, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
do_copy(struct sftp_conn *conn, const char *oldpath, const char *newpath)
|
sftp_copy(struct sftp_conn *conn, const char *oldpath, const char *newpath)
|
||||||
{
|
{
|
||||||
Attrib junk, *a;
|
Attrib junk, attr;
|
||||||
struct sshbuf *msg;
|
struct sshbuf *msg;
|
||||||
u_char *old_handle, *new_handle;
|
u_char *old_handle, *new_handle;
|
||||||
u_int mode, status, id;
|
u_int mode, status, id;
|
||||||
|
@ -1114,14 +1116,14 @@ do_copy(struct sftp_conn *conn, const char *oldpath, const char *newpath)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure the file exists, and we can copy its perms */
|
/* Make sure the file exists, and we can copy its perms */
|
||||||
if ((a = do_stat(conn, oldpath, 0)) == NULL)
|
if (sftp_stat(conn, oldpath, 0, &attr) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Do not preserve set[ug]id here, as we do not preserve ownership */
|
/* Do not preserve set[ug]id here, as we do not preserve ownership */
|
||||||
if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
|
if (attr.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
|
||||||
mode = a->perm & 0777;
|
mode = attr.perm & 0777;
|
||||||
|
|
||||||
if (!S_ISREG(a->perm)) {
|
if (!S_ISREG(attr.perm)) {
|
||||||
error("Cannot copy non-regular file: %s", oldpath);
|
error("Cannot copy non-regular file: %s", oldpath);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1131,9 +1133,9 @@ do_copy(struct sftp_conn *conn, const char *oldpath, const char *newpath)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set up the new perms for the new file */
|
/* Set up the new perms for the new file */
|
||||||
attrib_clear(a);
|
attrib_clear(&attr);
|
||||||
a->perm = mode;
|
attr.perm = mode;
|
||||||
a->flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
|
attr.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
|
||||||
|
|
||||||
if ((msg = sshbuf_new()) == NULL)
|
if ((msg = sshbuf_new()) == NULL)
|
||||||
fatal("%s: sshbuf_new failed", __func__);
|
fatal("%s: sshbuf_new failed", __func__);
|
||||||
|
@ -1167,7 +1169,7 @@ do_copy(struct sftp_conn *conn, const char *oldpath, const char *newpath)
|
||||||
(r = sshbuf_put_cstring(msg, newpath)) != 0 ||
|
(r = sshbuf_put_cstring(msg, newpath)) != 0 ||
|
||||||
(r = sshbuf_put_u32(msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|
|
(r = sshbuf_put_u32(msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|
|
||||||
SSH2_FXF_TRUNC)) != 0 ||
|
SSH2_FXF_TRUNC)) != 0 ||
|
||||||
(r = encode_attrib(msg, a)) != 0)
|
(r = encode_attrib(msg, &attr)) != 0)
|
||||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
send_msg(conn, msg);
|
send_msg(conn, msg);
|
||||||
debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, newpath);
|
debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, newpath);
|
||||||
|
@ -1204,8 +1206,8 @@ do_copy(struct sftp_conn *conn, const char *oldpath, const char *newpath)
|
||||||
|
|
||||||
/* Clean up everything */
|
/* Clean up everything */
|
||||||
sshbuf_free(msg);
|
sshbuf_free(msg);
|
||||||
do_close(conn, old_handle, old_handle_len);
|
sftp_close(conn, old_handle, old_handle_len);
|
||||||
do_close(conn, new_handle, new_handle_len);
|
sftp_close(conn, new_handle, new_handle_len);
|
||||||
free(old_handle);
|
free(old_handle);
|
||||||
free(new_handle);
|
free(new_handle);
|
||||||
|
|
||||||
|
@ -1213,7 +1215,7 @@ do_copy(struct sftp_conn *conn, const char *oldpath, const char *newpath)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
do_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath,
|
sftp_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath,
|
||||||
int force_legacy)
|
int force_legacy)
|
||||||
{
|
{
|
||||||
struct sshbuf *msg;
|
struct sshbuf *msg;
|
||||||
|
@ -1258,7 +1260,7 @@ do_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath,
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
do_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath)
|
sftp_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath)
|
||||||
{
|
{
|
||||||
struct sshbuf *msg;
|
struct sshbuf *msg;
|
||||||
u_int status, id;
|
u_int status, id;
|
||||||
|
@ -1296,7 +1298,7 @@ do_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
do_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath)
|
sftp_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath)
|
||||||
{
|
{
|
||||||
struct sshbuf *msg;
|
struct sshbuf *msg;
|
||||||
u_int status, id;
|
u_int status, id;
|
||||||
|
@ -1332,7 +1334,7 @@ do_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
do_fsync(struct sftp_conn *conn, u_char *handle, u_int handle_len)
|
sftp_fsync(struct sftp_conn *conn, u_char *handle, u_int handle_len)
|
||||||
{
|
{
|
||||||
struct sshbuf *msg;
|
struct sshbuf *msg;
|
||||||
u_int status, id;
|
u_int status, id;
|
||||||
|
@ -1365,7 +1367,7 @@ do_fsync(struct sftp_conn *conn, u_char *handle, u_int handle_len)
|
||||||
|
|
||||||
#ifdef notyet
|
#ifdef notyet
|
||||||
char *
|
char *
|
||||||
do_readlink(struct sftp_conn *conn, const char *path)
|
sftp_readlink(struct sftp_conn *conn, const char *path)
|
||||||
{
|
{
|
||||||
struct sshbuf *msg;
|
struct sshbuf *msg;
|
||||||
u_int expected_id, count, id;
|
u_int expected_id, count, id;
|
||||||
|
@ -1423,7 +1425,7 @@ do_readlink(struct sftp_conn *conn, const char *path)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int
|
int
|
||||||
do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st,
|
sftp_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st,
|
||||||
int quiet)
|
int quiet)
|
||||||
{
|
{
|
||||||
struct sshbuf *msg;
|
struct sshbuf *msg;
|
||||||
|
@ -1454,7 +1456,7 @@ do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st,
|
||||||
|
|
||||||
#ifdef notyet
|
#ifdef notyet
|
||||||
int
|
int
|
||||||
do_fstatvfs(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
|
sftp_fstatvfs(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
|
||||||
struct sftp_statvfs *st, int quiet)
|
struct sftp_statvfs *st, int quiet)
|
||||||
{
|
{
|
||||||
struct sshbuf *msg;
|
struct sshbuf *msg;
|
||||||
|
@ -1484,7 +1486,7 @@ do_fstatvfs(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int
|
int
|
||||||
do_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a)
|
sftp_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a)
|
||||||
{
|
{
|
||||||
struct sshbuf *msg;
|
struct sshbuf *msg;
|
||||||
u_int status, id;
|
u_int status, id;
|
||||||
|
@ -1592,7 +1594,7 @@ progress_meter_path(const char *path)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
do_download(struct sftp_conn *conn, const char *remote_path,
|
sftp_download(struct sftp_conn *conn, const char *remote_path,
|
||||||
const char *local_path, Attrib *a, int preserve_flag, int resume_flag,
|
const char *local_path, Attrib *a, int preserve_flag, int resume_flag,
|
||||||
int fsync_flag, int inplace_flag)
|
int fsync_flag, int inplace_flag)
|
||||||
{
|
{
|
||||||
|
@ -1608,14 +1610,18 @@ do_download(struct sftp_conn *conn, const char *remote_path,
|
||||||
struct requests requests;
|
struct requests requests;
|
||||||
struct request *req;
|
struct request *req;
|
||||||
u_char type;
|
u_char type;
|
||||||
|
Attrib attr;
|
||||||
|
|
||||||
debug2_f("download remote \"%s\" to local \"%s\"",
|
debug2_f("download remote \"%s\" to local \"%s\"",
|
||||||
remote_path, local_path);
|
remote_path, local_path);
|
||||||
|
|
||||||
TAILQ_INIT(&requests);
|
TAILQ_INIT(&requests);
|
||||||
|
|
||||||
if (a == NULL && (a = do_stat(conn, remote_path, 0)) == NULL)
|
if (a == NULL) {
|
||||||
|
if (sftp_stat(conn, remote_path, 0, &attr) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
a = &attr;
|
||||||
|
}
|
||||||
|
|
||||||
/* Do not preserve set[ug]id here, as we do not preserve ownership */
|
/* Do not preserve set[ug]id here, as we do not preserve ownership */
|
||||||
if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
|
if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
|
||||||
|
@ -1661,7 +1667,7 @@ do_download(struct sftp_conn *conn, const char *remote_path,
|
||||||
error("Unable to resume download of \"%s\": "
|
error("Unable to resume download of \"%s\": "
|
||||||
"local file is larger than remote", local_path);
|
"local file is larger than remote", local_path);
|
||||||
fail:
|
fail:
|
||||||
do_close(conn, handle, handle_len);
|
sftp_close(conn, handle, handle_len);
|
||||||
free(handle);
|
free(handle);
|
||||||
if (local_fd != -1)
|
if (local_fd != -1)
|
||||||
close(local_fd);
|
close(local_fd);
|
||||||
|
@ -1836,14 +1842,14 @@ do_download(struct sftp_conn *conn, const char *remote_path,
|
||||||
if (read_error) {
|
if (read_error) {
|
||||||
error("read remote \"%s\" : %s", remote_path, fx2txt(status));
|
error("read remote \"%s\" : %s", remote_path, fx2txt(status));
|
||||||
status = -1;
|
status = -1;
|
||||||
do_close(conn, handle, handle_len);
|
sftp_close(conn, handle, handle_len);
|
||||||
} else if (write_error) {
|
} else if (write_error) {
|
||||||
error("write local \"%s\": %s", local_path,
|
error("write local \"%s\": %s", local_path,
|
||||||
strerror(write_errno));
|
strerror(write_errno));
|
||||||
status = SSH2_FX_FAILURE;
|
status = SSH2_FX_FAILURE;
|
||||||
do_close(conn, handle, handle_len);
|
sftp_close(conn, handle, handle_len);
|
||||||
} else {
|
} else {
|
||||||
if (do_close(conn, handle, handle_len) != 0 || interrupted)
|
if (sftp_close(conn, handle, handle_len) != 0 || interrupted)
|
||||||
status = SSH2_FX_FAILURE;
|
status = SSH2_FX_FAILURE;
|
||||||
else
|
else
|
||||||
status = SSH2_FX_OK;
|
status = SSH2_FX_OK;
|
||||||
|
@ -1900,12 +1906,10 @@ download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
|
||||||
debug2_f("download dir remote \"%s\" to local \"%s\"", src, dst);
|
debug2_f("download dir remote \"%s\" to local \"%s\"", src, dst);
|
||||||
|
|
||||||
if (dirattrib == NULL) {
|
if (dirattrib == NULL) {
|
||||||
if ((a = do_stat(conn, src, 1)) == NULL) {
|
if (sftp_stat(conn, src, 1, &ldirattrib) != 0) {
|
||||||
error("stat remote \"%s\" directory failed", src);
|
error("stat remote \"%s\" directory failed", src);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/* Don't let this be clobbered by later do_stat calls */
|
|
||||||
ldirattrib = *a;
|
|
||||||
dirattrib = &ldirattrib;
|
dirattrib = &ldirattrib;
|
||||||
}
|
}
|
||||||
if (!S_ISDIR(dirattrib->perm)) {
|
if (!S_ISDIR(dirattrib->perm)) {
|
||||||
|
@ -1928,7 +1932,7 @@ download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (do_readdir(conn, src, &dir_entries) == -1) {
|
if (sftp_readdir(conn, src, &dir_entries) == -1) {
|
||||||
error("remote readdir \"%s\" failed", src);
|
error("remote readdir \"%s\" failed", src);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1938,8 +1942,8 @@ download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
|
||||||
free(new_src);
|
free(new_src);
|
||||||
|
|
||||||
filename = dir_entries[i]->filename;
|
filename = dir_entries[i]->filename;
|
||||||
new_dst = path_append(dst, filename);
|
new_dst = sftp_path_append(dst, filename);
|
||||||
new_src = path_append(src, filename);
|
new_src = sftp_path_append(src, filename);
|
||||||
|
|
||||||
a = &dir_entries[i]->a;
|
a = &dir_entries[i]->a;
|
||||||
if (S_ISLNK(a->perm)) {
|
if (S_ISLNK(a->perm)) {
|
||||||
|
@ -1949,13 +1953,11 @@ download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* Replace the stat contents with the symlink target */
|
/* Replace the stat contents with the symlink target */
|
||||||
if ((a = do_stat(conn, new_src, 1)) == NULL) {
|
if (sftp_stat(conn, new_src, 1, &lsym) != 0) {
|
||||||
logit("remote stat \"%s\" failed", new_src);
|
logit("remote stat \"%s\" failed", new_src);
|
||||||
ret = -1;
|
ret = -1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* Don't let this be clobbered by later do_stat calls */
|
|
||||||
lsym = *a;
|
|
||||||
a = &lsym;
|
a = &lsym;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1969,7 +1971,7 @@ download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
|
||||||
fsync_flag, follow_link_flag, inplace_flag) == -1)
|
fsync_flag, follow_link_flag, inplace_flag) == -1)
|
||||||
ret = -1;
|
ret = -1;
|
||||||
} else if (S_ISREG(a->perm)) {
|
} else if (S_ISREG(a->perm)) {
|
||||||
if (do_download(conn, new_src, new_dst, a,
|
if (sftp_download(conn, new_src, new_dst, a,
|
||||||
preserve_flag, resume_flag, fsync_flag,
|
preserve_flag, resume_flag, fsync_flag,
|
||||||
inplace_flag) == -1) {
|
inplace_flag) == -1) {
|
||||||
error("Download of file %s to %s failed",
|
error("Download of file %s to %s failed",
|
||||||
|
@ -2001,20 +2003,20 @@ download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
|
||||||
error("local chmod directory \"%s\": %s", dst,
|
error("local chmod directory \"%s\": %s", dst,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
|
|
||||||
free_sftp_dirents(dir_entries);
|
sftp_free_dirents(dir_entries);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
download_dir(struct sftp_conn *conn, const char *src, const char *dst,
|
sftp_download_dir(struct sftp_conn *conn, const char *src, const char *dst,
|
||||||
Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag,
|
Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag,
|
||||||
int fsync_flag, int follow_link_flag, int inplace_flag)
|
int fsync_flag, int follow_link_flag, int inplace_flag)
|
||||||
{
|
{
|
||||||
char *src_canon;
|
char *src_canon;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if ((src_canon = do_realpath(conn, src)) == NULL) {
|
if ((src_canon = sftp_realpath(conn, src)) == NULL) {
|
||||||
error("download \"%s\": path canonicalization failed", src);
|
error("download \"%s\": path canonicalization failed", src);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -2027,7 +2029,7 @@ download_dir(struct sftp_conn *conn, const char *src, const char *dst,
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
do_upload(struct sftp_conn *conn, const char *local_path,
|
sftp_upload(struct sftp_conn *conn, const char *local_path,
|
||||||
const char *remote_path, int preserve_flag, int resume,
|
const char *remote_path, int preserve_flag, int resume,
|
||||||
int fsync_flag, int inplace_flag)
|
int fsync_flag, int inplace_flag)
|
||||||
{
|
{
|
||||||
|
@ -2037,7 +2039,7 @@ do_upload(struct sftp_conn *conn, const char *local_path,
|
||||||
u_char type, *handle, *data;
|
u_char type, *handle, *data;
|
||||||
struct sshbuf *msg;
|
struct sshbuf *msg;
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
Attrib a, t, *c = NULL;
|
Attrib a, t, c;
|
||||||
u_int32_t startid, ackid;
|
u_int32_t startid, ackid;
|
||||||
u_int64_t highwater = 0, maxack = 0;
|
u_int64_t highwater = 0, maxack = 0;
|
||||||
struct request *ack = NULL;
|
struct request *ack = NULL;
|
||||||
|
@ -2073,19 +2075,19 @@ do_upload(struct sftp_conn *conn, const char *local_path,
|
||||||
|
|
||||||
if (resume) {
|
if (resume) {
|
||||||
/* Get remote file size if it exists */
|
/* Get remote file size if it exists */
|
||||||
if ((c = do_stat(conn, remote_path, 0)) == NULL) {
|
if (sftp_stat(conn, remote_path, 0, &c) != 0) {
|
||||||
close(local_fd);
|
close(local_fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((off_t)c->size >= sb.st_size) {
|
if ((off_t)c.size >= sb.st_size) {
|
||||||
error("resume \"%s\": destination file "
|
error("resume \"%s\": destination file "
|
||||||
"same size or larger", local_path);
|
"same size or larger", local_path);
|
||||||
close(local_fd);
|
close(local_fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lseek(local_fd, (off_t)c->size, SEEK_SET) == -1) {
|
if (lseek(local_fd, (off_t)c.size, SEEK_SET) == -1) {
|
||||||
close(local_fd);
|
close(local_fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -2109,7 +2111,7 @@ do_upload(struct sftp_conn *conn, const char *local_path,
|
||||||
data = xmalloc(conn->upload_buflen);
|
data = xmalloc(conn->upload_buflen);
|
||||||
|
|
||||||
/* Read from local and write to remote */
|
/* Read from local and write to remote */
|
||||||
offset = progress_counter = (resume ? c->size : 0);
|
offset = progress_counter = (resume ? c.size : 0);
|
||||||
if (showprogress) {
|
if (showprogress) {
|
||||||
start_progress_meter(progress_meter_path(local_path),
|
start_progress_meter(progress_meter_path(local_path),
|
||||||
sb.st_size, &progress_counter);
|
sb.st_size, &progress_counter);
|
||||||
|
@ -2221,7 +2223,7 @@ do_upload(struct sftp_conn *conn, const char *local_path,
|
||||||
attrib_clear(&t);
|
attrib_clear(&t);
|
||||||
t.flags = SSH2_FILEXFER_ATTR_SIZE;
|
t.flags = SSH2_FILEXFER_ATTR_SIZE;
|
||||||
t.size = highwater;
|
t.size = highwater;
|
||||||
do_fsetstat(conn, handle, handle_len, &t);
|
sftp_fsetstat(conn, handle, handle_len, &t);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (close(local_fd) == -1) {
|
if (close(local_fd) == -1) {
|
||||||
|
@ -2231,12 +2233,12 @@ do_upload(struct sftp_conn *conn, const char *local_path,
|
||||||
|
|
||||||
/* Override umask and utimes if asked */
|
/* Override umask and utimes if asked */
|
||||||
if (preserve_flag)
|
if (preserve_flag)
|
||||||
do_fsetstat(conn, handle, handle_len, &a);
|
sftp_fsetstat(conn, handle, handle_len, &a);
|
||||||
|
|
||||||
if (fsync_flag)
|
if (fsync_flag)
|
||||||
(void)do_fsync(conn, handle, handle_len);
|
(void)sftp_fsync(conn, handle, handle_len);
|
||||||
|
|
||||||
if (do_close(conn, handle, handle_len) != 0)
|
if (sftp_close(conn, handle, handle_len) != 0)
|
||||||
status = SSH2_FX_FAILURE;
|
status = SSH2_FX_FAILURE;
|
||||||
|
|
||||||
free(handle);
|
free(handle);
|
||||||
|
@ -2254,7 +2256,7 @@ upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
|
||||||
struct dirent *dp;
|
struct dirent *dp;
|
||||||
char *filename, *new_src = NULL, *new_dst = NULL;
|
char *filename, *new_src = NULL, *new_dst = NULL;
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
Attrib a, *dirattrib;
|
Attrib a, dirattrib;
|
||||||
u_int32_t saved_perm;
|
u_int32_t saved_perm;
|
||||||
|
|
||||||
debug2_f("upload local dir \"%s\" to remote \"%s\"", src, dst);
|
debug2_f("upload local dir \"%s\" to remote \"%s\"", src, dst);
|
||||||
|
@ -2290,10 +2292,10 @@ upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
|
||||||
*/
|
*/
|
||||||
saved_perm = a.perm;
|
saved_perm = a.perm;
|
||||||
a.perm |= (S_IWUSR|S_IXUSR);
|
a.perm |= (S_IWUSR|S_IXUSR);
|
||||||
if (do_mkdir(conn, dst, &a, 0) != 0) {
|
if (sftp_mkdir(conn, dst, &a, 0) != 0) {
|
||||||
if ((dirattrib = do_stat(conn, dst, 0)) == NULL)
|
if (sftp_stat(conn, dst, 0, &dirattrib) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (!S_ISDIR(dirattrib->perm)) {
|
if (!S_ISDIR(dirattrib.perm)) {
|
||||||
error("\"%s\" exists but is not a directory", dst);
|
error("\"%s\" exists but is not a directory", dst);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -2311,8 +2313,8 @@ upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
|
||||||
free(new_dst);
|
free(new_dst);
|
||||||
free(new_src);
|
free(new_src);
|
||||||
filename = dp->d_name;
|
filename = dp->d_name;
|
||||||
new_dst = path_append(dst, filename);
|
new_dst = sftp_path_append(dst, filename);
|
||||||
new_src = path_append(src, filename);
|
new_src = sftp_path_append(src, filename);
|
||||||
|
|
||||||
if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0)
|
if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0)
|
||||||
continue;
|
continue;
|
||||||
|
@ -2341,7 +2343,7 @@ upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
|
||||||
fsync_flag, follow_link_flag, inplace_flag) == -1)
|
fsync_flag, follow_link_flag, inplace_flag) == -1)
|
||||||
ret = -1;
|
ret = -1;
|
||||||
} else if (S_ISREG(sb.st_mode)) {
|
} else if (S_ISREG(sb.st_mode)) {
|
||||||
if (do_upload(conn, new_src, new_dst,
|
if (sftp_upload(conn, new_src, new_dst,
|
||||||
preserve_flag, resume, fsync_flag,
|
preserve_flag, resume, fsync_flag,
|
||||||
inplace_flag) == -1) {
|
inplace_flag) == -1) {
|
||||||
error("upload \"%s\" to \"%s\" failed",
|
error("upload \"%s\" to \"%s\" failed",
|
||||||
|
@ -2354,21 +2356,21 @@ upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
|
||||||
free(new_dst);
|
free(new_dst);
|
||||||
free(new_src);
|
free(new_src);
|
||||||
|
|
||||||
do_setstat(conn, dst, &a);
|
sftp_setstat(conn, dst, &a);
|
||||||
|
|
||||||
(void) closedir(dirp);
|
(void) closedir(dirp);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
upload_dir(struct sftp_conn *conn, const char *src, const char *dst,
|
sftp_upload_dir(struct sftp_conn *conn, const char *src, const char *dst,
|
||||||
int preserve_flag, int print_flag, int resume, int fsync_flag,
|
int preserve_flag, int print_flag, int resume, int fsync_flag,
|
||||||
int follow_link_flag, int inplace_flag)
|
int follow_link_flag, int inplace_flag)
|
||||||
{
|
{
|
||||||
char *dst_canon;
|
char *dst_canon;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if ((dst_canon = do_realpath(conn, dst)) == NULL) {
|
if ((dst_canon = sftp_realpath(conn, dst)) == NULL) {
|
||||||
error("upload \"%s\": path canonicalization failed", dst);
|
error("upload \"%s\": path canonicalization failed", dst);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -2427,13 +2429,13 @@ handle_dest_replies(struct sftp_conn *to, const char *to_path, int synchronous,
|
||||||
*write_errorp = status;
|
*write_errorp = status;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* XXX this doesn't do full reply matching like do_upload and
|
* XXX this doesn't do full reply matching like sftp_upload and
|
||||||
* so cannot gracefully truncate terminated uploads at a
|
* so cannot gracefully truncate terminated uploads at a
|
||||||
* high-water mark. ATM the only caller of this function (scp)
|
* high-water mark. ATM the only caller of this function (scp)
|
||||||
* doesn't support transfer resumption, so this doesn't matter
|
* doesn't support transfer resumption, so this doesn't matter
|
||||||
* a whole lot.
|
* a whole lot.
|
||||||
*
|
*
|
||||||
* To be safe, do_crossload truncates the destination file to
|
* To be safe, sftp_crossload truncates the destination file to
|
||||||
* zero length on upload failure, since we can't trust the
|
* zero length on upload failure, since we can't trust the
|
||||||
* server not to have reordered replies that could have
|
* server not to have reordered replies that could have
|
||||||
* inserted holes where none existed in the source file.
|
* inserted holes where none existed in the source file.
|
||||||
|
@ -2448,7 +2450,7 @@ handle_dest_replies(struct sftp_conn *to, const char *to_path, int synchronous,
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
do_crossload(struct sftp_conn *from, struct sftp_conn *to,
|
sftp_crossload(struct sftp_conn *from, struct sftp_conn *to,
|
||||||
const char *from_path, const char *to_path,
|
const char *from_path, const char *to_path,
|
||||||
Attrib *a, int preserve_flag)
|
Attrib *a, int preserve_flag)
|
||||||
{
|
{
|
||||||
|
@ -2463,13 +2465,17 @@ do_crossload(struct sftp_conn *from, struct sftp_conn *to,
|
||||||
struct requests requests;
|
struct requests requests;
|
||||||
struct request *req;
|
struct request *req;
|
||||||
u_char type;
|
u_char type;
|
||||||
|
Attrib attr;
|
||||||
|
|
||||||
debug2_f("crossload src \"%s\" to dst \"%s\"", from_path, to_path);
|
debug2_f("crossload src \"%s\" to dst \"%s\"", from_path, to_path);
|
||||||
|
|
||||||
TAILQ_INIT(&requests);
|
TAILQ_INIT(&requests);
|
||||||
|
|
||||||
if (a == NULL && (a = do_stat(from, from_path, 0)) == NULL)
|
if (a == NULL) {
|
||||||
|
if (sftp_stat(from, from_path, 0, &attr) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
a = &attr;
|
||||||
|
}
|
||||||
|
|
||||||
if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&
|
if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&
|
||||||
(!S_ISREG(a->perm))) {
|
(!S_ISREG(a->perm))) {
|
||||||
|
@ -2499,7 +2505,7 @@ do_crossload(struct sftp_conn *from, struct sftp_conn *to,
|
||||||
if (send_open(to, to_path, "dest",
|
if (send_open(to, to_path, "dest",
|
||||||
SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC, a,
|
SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC, a,
|
||||||
&to_handle, &to_handle_len) != 0) {
|
&to_handle, &to_handle_len) != 0) {
|
||||||
do_close(from, from_handle, from_handle_len);
|
sftp_close(from, from_handle, from_handle_len);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2649,7 +2655,7 @@ do_crossload(struct sftp_conn *from, struct sftp_conn *to,
|
||||||
/* Truncate at 0 length on interrupt or error to avoid holes at dest */
|
/* Truncate at 0 length on interrupt or error to avoid holes at dest */
|
||||||
if (read_error || write_error || interrupted) {
|
if (read_error || write_error || interrupted) {
|
||||||
debug("truncating \"%s\" at 0", to_path);
|
debug("truncating \"%s\" at 0", to_path);
|
||||||
do_close(to, to_handle, to_handle_len);
|
sftp_close(to, to_handle, to_handle_len);
|
||||||
free(to_handle);
|
free(to_handle);
|
||||||
if (send_open(to, to_path, "dest",
|
if (send_open(to, to_path, "dest",
|
||||||
SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC, a,
|
SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC, a,
|
||||||
|
@ -2661,17 +2667,17 @@ do_crossload(struct sftp_conn *from, struct sftp_conn *to,
|
||||||
if (read_error) {
|
if (read_error) {
|
||||||
error("read origin \"%s\": %s", from_path, fx2txt(status));
|
error("read origin \"%s\": %s", from_path, fx2txt(status));
|
||||||
status = -1;
|
status = -1;
|
||||||
do_close(from, from_handle, from_handle_len);
|
sftp_close(from, from_handle, from_handle_len);
|
||||||
if (to_handle != NULL)
|
if (to_handle != NULL)
|
||||||
do_close(to, to_handle, to_handle_len);
|
sftp_close(to, to_handle, to_handle_len);
|
||||||
} else if (write_error) {
|
} else if (write_error) {
|
||||||
error("write dest \"%s\": %s", to_path, fx2txt(write_error));
|
error("write dest \"%s\": %s", to_path, fx2txt(write_error));
|
||||||
status = SSH2_FX_FAILURE;
|
status = SSH2_FX_FAILURE;
|
||||||
do_close(from, from_handle, from_handle_len);
|
sftp_close(from, from_handle, from_handle_len);
|
||||||
if (to_handle != NULL)
|
if (to_handle != NULL)
|
||||||
do_close(to, to_handle, to_handle_len);
|
sftp_close(to, to_handle, to_handle_len);
|
||||||
} else {
|
} else {
|
||||||
if (do_close(from, from_handle, from_handle_len) != 0 ||
|
if (sftp_close(from, from_handle, from_handle_len) != 0 ||
|
||||||
interrupted)
|
interrupted)
|
||||||
status = -1;
|
status = -1;
|
||||||
else
|
else
|
||||||
|
@ -2679,8 +2685,8 @@ do_crossload(struct sftp_conn *from, struct sftp_conn *to,
|
||||||
if (to_handle != NULL) {
|
if (to_handle != NULL) {
|
||||||
/* Need to resend utimes after write */
|
/* Need to resend utimes after write */
|
||||||
if (preserve_flag)
|
if (preserve_flag)
|
||||||
do_fsetstat(to, to_handle, to_handle_len, a);
|
sftp_fsetstat(to, to_handle, to_handle_len, a);
|
||||||
do_close(to, to_handle, to_handle_len);
|
sftp_close(to, to_handle, to_handle_len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sshbuf_free(msg);
|
sshbuf_free(msg);
|
||||||
|
@ -2700,7 +2706,7 @@ crossload_dir_internal(struct sftp_conn *from, struct sftp_conn *to,
|
||||||
SFTP_DIRENT **dir_entries;
|
SFTP_DIRENT **dir_entries;
|
||||||
char *filename, *new_from_path = NULL, *new_to_path = NULL;
|
char *filename, *new_from_path = NULL, *new_to_path = NULL;
|
||||||
mode_t mode = 0777;
|
mode_t mode = 0777;
|
||||||
Attrib curdir;
|
Attrib curdir, ldirattrib, newdir;
|
||||||
|
|
||||||
debug2_f("crossload dir src \"%s\" to dst \"%s\"", from_path, to_path);
|
debug2_f("crossload dir src \"%s\" to dst \"%s\"", from_path, to_path);
|
||||||
|
|
||||||
|
@ -2709,11 +2715,13 @@ crossload_dir_internal(struct sftp_conn *from, struct sftp_conn *to,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dirattrib == NULL &&
|
if (dirattrib == NULL) {
|
||||||
(dirattrib = do_stat(from, from_path, 1)) == NULL) {
|
if (sftp_stat(from, from_path, 1, &ldirattrib) != 0) {
|
||||||
error("stat remote \"%s\" failed", from_path);
|
error("stat remote \"%s\" failed", from_path);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
dirattrib = &ldirattrib;
|
||||||
|
}
|
||||||
if (!S_ISDIR(dirattrib->perm)) {
|
if (!S_ISDIR(dirattrib->perm)) {
|
||||||
error("\"%s\" is not a directory", from_path);
|
error("\"%s\" is not a directory", from_path);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -2740,17 +2748,17 @@ crossload_dir_internal(struct sftp_conn *from, struct sftp_conn *to,
|
||||||
* the path already existed and is a directory. Ensure we can
|
* the path already existed and is a directory. Ensure we can
|
||||||
* write to the directory we create for the duration of the transfer.
|
* write to the directory we create for the duration of the transfer.
|
||||||
*/
|
*/
|
||||||
if (do_mkdir(to, to_path, &curdir, 0) != 0) {
|
if (sftp_mkdir(to, to_path, &curdir, 0) != 0) {
|
||||||
if ((dirattrib = do_stat(to, to_path, 0)) == NULL)
|
if (sftp_stat(to, to_path, 0, &newdir) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (!S_ISDIR(dirattrib->perm)) {
|
if (!S_ISDIR(newdir.perm)) {
|
||||||
error("\"%s\" exists but is not a directory", to_path);
|
error("\"%s\" exists but is not a directory", to_path);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
curdir.perm = mode;
|
curdir.perm = mode;
|
||||||
|
|
||||||
if (do_readdir(from, from_path, &dir_entries) == -1) {
|
if (sftp_readdir(from, from_path, &dir_entries) == -1) {
|
||||||
error("origin readdir \"%s\" failed", from_path);
|
error("origin readdir \"%s\" failed", from_path);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -2760,8 +2768,8 @@ crossload_dir_internal(struct sftp_conn *from, struct sftp_conn *to,
|
||||||
free(new_to_path);
|
free(new_to_path);
|
||||||
|
|
||||||
filename = dir_entries[i]->filename;
|
filename = dir_entries[i]->filename;
|
||||||
new_from_path = path_append(from_path, filename);
|
new_from_path = sftp_path_append(from_path, filename);
|
||||||
new_to_path = path_append(to_path, filename);
|
new_to_path = sftp_path_append(to_path, filename);
|
||||||
|
|
||||||
if (S_ISDIR(dir_entries[i]->a.perm)) {
|
if (S_ISDIR(dir_entries[i]->a.perm)) {
|
||||||
if (strcmp(filename, ".") == 0 ||
|
if (strcmp(filename, ".") == 0 ||
|
||||||
|
@ -2776,10 +2784,10 @@ crossload_dir_internal(struct sftp_conn *from, struct sftp_conn *to,
|
||||||
(follow_link_flag && S_ISLNK(dir_entries[i]->a.perm))) {
|
(follow_link_flag && S_ISLNK(dir_entries[i]->a.perm))) {
|
||||||
/*
|
/*
|
||||||
* If this is a symlink then don't send the link's
|
* If this is a symlink then don't send the link's
|
||||||
* Attrib. do_download() will do a FXP_STAT operation
|
* Attrib. sftp_download() will do a FXP_STAT operation
|
||||||
* and get the link target's attributes.
|
* and get the link target's attributes.
|
||||||
*/
|
*/
|
||||||
if (do_crossload(from, to, new_from_path, new_to_path,
|
if (sftp_crossload(from, to, new_from_path, new_to_path,
|
||||||
S_ISLNK(dir_entries[i]->a.perm) ? NULL :
|
S_ISLNK(dir_entries[i]->a.perm) ? NULL :
|
||||||
&(dir_entries[i]->a), preserve_flag) == -1) {
|
&(dir_entries[i]->a), preserve_flag) == -1) {
|
||||||
error("crossload \"%s\" to \"%s\" failed",
|
error("crossload \"%s\" to \"%s\" failed",
|
||||||
|
@ -2794,22 +2802,22 @@ crossload_dir_internal(struct sftp_conn *from, struct sftp_conn *to,
|
||||||
free(new_to_path);
|
free(new_to_path);
|
||||||
free(new_from_path);
|
free(new_from_path);
|
||||||
|
|
||||||
do_setstat(to, to_path, &curdir);
|
sftp_setstat(to, to_path, &curdir);
|
||||||
|
|
||||||
free_sftp_dirents(dir_entries);
|
sftp_free_dirents(dir_entries);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
crossload_dir(struct sftp_conn *from, struct sftp_conn *to,
|
sftp_crossload_dir(struct sftp_conn *from, struct sftp_conn *to,
|
||||||
const char *from_path, const char *to_path,
|
const char *from_path, const char *to_path,
|
||||||
Attrib *dirattrib, int preserve_flag, int print_flag, int follow_link_flag)
|
Attrib *dirattrib, int preserve_flag, int print_flag, int follow_link_flag)
|
||||||
{
|
{
|
||||||
char *from_path_canon;
|
char *from_path_canon;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if ((from_path_canon = do_realpath(from, from_path)) == NULL) {
|
if ((from_path_canon = sftp_realpath(from, from_path)) == NULL) {
|
||||||
error("crossload \"%s\": path canonicalization failed",
|
error("crossload \"%s\": path canonicalization failed",
|
||||||
from_path);
|
from_path);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -2822,13 +2830,13 @@ crossload_dir(struct sftp_conn *from, struct sftp_conn *to,
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
can_get_users_groups_by_id(struct sftp_conn *conn)
|
sftp_can_get_users_groups_by_id(struct sftp_conn *conn)
|
||||||
{
|
{
|
||||||
return (conn->exts & SFTP_EXT_GETUSERSGROUPS_BY_ID) != 0;
|
return (conn->exts & SFTP_EXT_GETUSERSGROUPS_BY_ID) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
do_get_users_groups_by_id(struct sftp_conn *conn,
|
sftp_get_users_groups_by_id(struct sftp_conn *conn,
|
||||||
const u_int *uids, u_int nuids,
|
const u_int *uids, u_int nuids,
|
||||||
const u_int *gids, u_int ngids,
|
const u_int *gids, u_int ngids,
|
||||||
char ***usernamesp, char ***groupnamesp)
|
char ***usernamesp, char ***groupnamesp)
|
||||||
|
@ -2840,7 +2848,7 @@ do_get_users_groups_by_id(struct sftp_conn *conn,
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
*usernamesp = *groupnamesp = NULL;
|
*usernamesp = *groupnamesp = NULL;
|
||||||
if (!can_get_users_groups_by_id(conn))
|
if (!sftp_can_get_users_groups_by_id(conn))
|
||||||
return SSH_ERR_FEATURE_UNSUPPORTED;
|
return SSH_ERR_FEATURE_UNSUPPORTED;
|
||||||
|
|
||||||
if ((msg = sshbuf_new()) == NULL ||
|
if ((msg = sshbuf_new()) == NULL ||
|
||||||
|
@ -2936,7 +2944,7 @@ do_get_users_groups_by_id(struct sftp_conn *conn,
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
path_append(const char *p1, const char *p2)
|
sftp_path_append(const char *p1, const char *p2)
|
||||||
{
|
{
|
||||||
char *ret;
|
char *ret;
|
||||||
size_t len = strlen(p1) + strlen(p2) + 2;
|
size_t len = strlen(p1) + strlen(p2) + 2;
|
||||||
|
@ -2955,13 +2963,13 @@ path_append(const char *p1, const char *p2)
|
||||||
* freed and a replacement allocated. Caller must free returned string.
|
* freed and a replacement allocated. Caller must free returned string.
|
||||||
*/
|
*/
|
||||||
char *
|
char *
|
||||||
make_absolute(char *p, const char *pwd)
|
sftp_make_absolute(char *p, const char *pwd)
|
||||||
{
|
{
|
||||||
char *abs_str;
|
char *abs_str;
|
||||||
|
|
||||||
/* Derelativise */
|
/* Derelativise */
|
||||||
if (p && !path_absolute(p)) {
|
if (p && !path_absolute(p)) {
|
||||||
abs_str = path_append(pwd, p);
|
abs_str = sftp_path_append(pwd, p);
|
||||||
free(p);
|
free(p);
|
||||||
return(abs_str);
|
return(abs_str);
|
||||||
} else
|
} else
|
||||||
|
@ -2969,34 +2977,22 @@ make_absolute(char *p, const char *pwd)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
remote_is_dir(struct sftp_conn *conn, const char *path)
|
sftp_remote_is_dir(struct sftp_conn *conn, const char *path)
|
||||||
{
|
{
|
||||||
Attrib *a;
|
Attrib a;
|
||||||
|
|
||||||
/* XXX: report errors? */
|
/* XXX: report errors? */
|
||||||
if ((a = do_stat(conn, path, 1)) == NULL)
|
if (sftp_stat(conn, path, 1, &a) != 0)
|
||||||
return(0);
|
return(0);
|
||||||
if (!(a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS))
|
if (!(a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS))
|
||||||
return(0);
|
return(0);
|
||||||
return(S_ISDIR(a->perm));
|
return S_ISDIR(a.perm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
local_is_dir(const char *path)
|
|
||||||
{
|
|
||||||
struct stat sb;
|
|
||||||
|
|
||||||
/* XXX: report errors? */
|
|
||||||
if (stat(path, &sb) == -1)
|
|
||||||
return(0);
|
|
||||||
|
|
||||||
return(S_ISDIR(sb.st_mode));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check whether path returned from glob(..., GLOB_MARK, ...) is a directory */
|
/* Check whether path returned from glob(..., GLOB_MARK, ...) is a directory */
|
||||||
int
|
int
|
||||||
globpath_is_dir(const char *pathname)
|
sftp_globpath_is_dir(const char *pathname)
|
||||||
{
|
{
|
||||||
size_t l = strlen(pathname);
|
size_t l = strlen(pathname);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: sftp-client.h,v 1.38 2022/09/19 10:43:12 djm Exp $ */
|
/* $OpenBSD: sftp-client.h,v 1.39 2023/09/08 05:56:13 djm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
|
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
|
||||||
|
@ -70,107 +70,106 @@ struct sftp_limits {
|
||||||
* Initialise a SSH filexfer connection. Returns NULL on error or
|
* Initialise a SSH filexfer connection. Returns NULL on error or
|
||||||
* a pointer to a initialized sftp_conn struct on success.
|
* a pointer to a initialized sftp_conn struct on success.
|
||||||
*/
|
*/
|
||||||
struct sftp_conn *do_init(int, int, u_int, u_int, u_int64_t);
|
struct sftp_conn *sftp_init(int, int, u_int, u_int, u_int64_t);
|
||||||
|
|
||||||
u_int sftp_proto_version(struct sftp_conn *);
|
u_int sftp_proto_version(struct sftp_conn *);
|
||||||
|
|
||||||
/* Query server limits */
|
/* Query server limits */
|
||||||
int do_limits(struct sftp_conn *, struct sftp_limits *);
|
int sftp_get_limits(struct sftp_conn *, struct sftp_limits *);
|
||||||
|
|
||||||
/* Close file referred to by 'handle' */
|
/* Close file referred to by 'handle' */
|
||||||
int do_close(struct sftp_conn *, const u_char *, u_int);
|
int sftp_close(struct sftp_conn *, const u_char *, u_int);
|
||||||
|
|
||||||
/* Read contents of 'path' to NULL-terminated array 'dir' */
|
/* Read contents of 'path' to NULL-terminated array 'dir' */
|
||||||
int do_readdir(struct sftp_conn *, const char *, SFTP_DIRENT ***);
|
int sftp_readdir(struct sftp_conn *, const char *, SFTP_DIRENT ***);
|
||||||
|
|
||||||
/* Frees a NULL-terminated array of SFTP_DIRENTs (eg. from do_readdir) */
|
/* Frees a NULL-terminated array of SFTP_DIRENTs (eg. from sftp_readdir) */
|
||||||
void free_sftp_dirents(SFTP_DIRENT **);
|
void sftp_free_dirents(SFTP_DIRENT **);
|
||||||
|
|
||||||
/* Delete file 'path' */
|
/* Delete file 'path' */
|
||||||
int do_rm(struct sftp_conn *, const char *);
|
int sftp_rm(struct sftp_conn *, const char *);
|
||||||
|
|
||||||
/* Create directory 'path' */
|
/* Create directory 'path' */
|
||||||
int do_mkdir(struct sftp_conn *, const char *, Attrib *, int);
|
int sftp_mkdir(struct sftp_conn *, const char *, Attrib *, int);
|
||||||
|
|
||||||
/* Remove directory 'path' */
|
/* Remove directory 'path' */
|
||||||
int do_rmdir(struct sftp_conn *, const char *);
|
int sftp_rmdir(struct sftp_conn *, const char *);
|
||||||
|
|
||||||
/* Get file attributes of 'path' (follows symlinks) */
|
/* Get file attributes of 'path' (follows symlinks) */
|
||||||
Attrib *do_stat(struct sftp_conn *, const char *, int);
|
int sftp_stat(struct sftp_conn *, const char *, int, Attrib *);
|
||||||
|
|
||||||
/* Get file attributes of 'path' (does not follow symlinks) */
|
/* Get file attributes of 'path' (does not follow symlinks) */
|
||||||
Attrib *do_lstat(struct sftp_conn *, const char *, int);
|
int sftp_lstat(struct sftp_conn *, const char *, int, Attrib *);
|
||||||
|
|
||||||
/* Set file attributes of 'path' */
|
/* Set file attributes of 'path' */
|
||||||
int do_setstat(struct sftp_conn *, const char *, Attrib *);
|
int sftp_setstat(struct sftp_conn *, const char *, Attrib *);
|
||||||
|
|
||||||
/* Set file attributes of open file 'handle' */
|
/* Set file attributes of open file 'handle' */
|
||||||
int do_fsetstat(struct sftp_conn *, const u_char *, u_int, Attrib *);
|
int sftp_fsetstat(struct sftp_conn *, const u_char *, u_int, Attrib *);
|
||||||
|
|
||||||
/* Set file attributes of 'path', not following symlinks */
|
/* Set file attributes of 'path', not following symlinks */
|
||||||
int do_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a);
|
int sftp_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a);
|
||||||
|
|
||||||
/* Canonicalise 'path' - caller must free result */
|
/* Canonicalise 'path' - caller must free result */
|
||||||
char *do_realpath(struct sftp_conn *, const char *);
|
char *sftp_realpath(struct sftp_conn *, const char *);
|
||||||
|
|
||||||
/* Canonicalisation with tilde expansion (requires server extension) */
|
/* Canonicalisation with tilde expansion (requires server extension) */
|
||||||
char *do_expand_path(struct sftp_conn *, const char *);
|
char *sftp_expand_path(struct sftp_conn *, const char *);
|
||||||
|
|
||||||
/* Returns non-zero if server can tilde-expand paths */
|
/* Returns non-zero if server can tilde-expand paths */
|
||||||
int can_expand_path(struct sftp_conn *);
|
int sftp_can_expand_path(struct sftp_conn *);
|
||||||
|
|
||||||
/* Get statistics for filesystem hosting file at "path" */
|
/* Get statistics for filesystem hosting file at "path" */
|
||||||
int do_statvfs(struct sftp_conn *, const char *, struct sftp_statvfs *, int);
|
int sftp_statvfs(struct sftp_conn *, const char *, struct sftp_statvfs *, int);
|
||||||
|
|
||||||
/* Rename 'oldpath' to 'newpath' */
|
/* Rename 'oldpath' to 'newpath' */
|
||||||
int do_rename(struct sftp_conn *, const char *, const char *, int);
|
int sftp_rename(struct sftp_conn *, const char *, const char *, int);
|
||||||
|
|
||||||
/* Copy 'oldpath' to 'newpath' */
|
/* Copy 'oldpath' to 'newpath' */
|
||||||
int do_copy(struct sftp_conn *, const char *, const char *);
|
int sftp_copy(struct sftp_conn *, const char *, const char *);
|
||||||
|
|
||||||
/* Link 'oldpath' to 'newpath' */
|
/* Link 'oldpath' to 'newpath' */
|
||||||
int do_hardlink(struct sftp_conn *, const char *, const char *);
|
int sftp_hardlink(struct sftp_conn *, const char *, const char *);
|
||||||
|
|
||||||
/* Rename 'oldpath' to 'newpath' */
|
/* Rename 'oldpath' to 'newpath' */
|
||||||
int do_symlink(struct sftp_conn *, const char *, const char *);
|
int sftp_symlink(struct sftp_conn *, const char *, const char *);
|
||||||
|
|
||||||
/* Call fsync() on open file 'handle' */
|
/* Call fsync() on open file 'handle' */
|
||||||
int do_fsync(struct sftp_conn *conn, u_char *, u_int);
|
int sftp_fsync(struct sftp_conn *conn, u_char *, u_int);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Download 'remote_path' to 'local_path'. Preserve permissions and times
|
* Download 'remote_path' to 'local_path'. Preserve permissions and times
|
||||||
* if 'pflag' is set
|
* if 'pflag' is set
|
||||||
*/
|
*/
|
||||||
int do_download(struct sftp_conn *, const char *, const char *, Attrib *,
|
int sftp_download(struct sftp_conn *, const char *, const char *, Attrib *,
|
||||||
int, int, int, int);
|
int, int, int, int);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Recursively download 'remote_directory' to 'local_directory'. Preserve
|
* Recursively download 'remote_directory' to 'local_directory'. Preserve
|
||||||
* times if 'pflag' is set
|
* times if 'pflag' is set
|
||||||
*/
|
*/
|
||||||
int download_dir(struct sftp_conn *, const char *, const char *, Attrib *,
|
int sftp_download_dir(struct sftp_conn *, const char *, const char *, Attrib *,
|
||||||
int, int, int, int, int, int);
|
int, int, int, int, int, int);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Upload 'local_path' to 'remote_path'. Preserve permissions and times
|
* Upload 'local_path' to 'remote_path'. Preserve permissions and times
|
||||||
* if 'pflag' is set
|
* if 'pflag' is set
|
||||||
*/
|
*/
|
||||||
int do_upload(struct sftp_conn *, const char *, const char *,
|
int sftp_upload(struct sftp_conn *, const char *, const char *,
|
||||||
int, int, int, int);
|
int, int, int, int);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Recursively upload 'local_directory' to 'remote_directory'. Preserve
|
* Recursively upload 'local_directory' to 'remote_directory'. Preserve
|
||||||
* times if 'pflag' is set
|
* times if 'pflag' is set
|
||||||
*/
|
*/
|
||||||
int upload_dir(struct sftp_conn *, const char *, const char *,
|
int sftp_upload_dir(struct sftp_conn *, const char *, const char *,
|
||||||
int, int, int, int, int, int);
|
int, int, int, int, int, int);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Download a 'from_path' from the 'from' connection and upload it to
|
* Download a 'from_path' from the 'from' connection and upload it to
|
||||||
* to 'to' connection at 'to_path'.
|
* to 'to' connection at 'to_path'.
|
||||||
*/
|
*/
|
||||||
int
|
int sftp_crossload(struct sftp_conn *from, struct sftp_conn *to,
|
||||||
do_crossload(struct sftp_conn *from, struct sftp_conn *to,
|
|
||||||
const char *from_path, const char *to_path,
|
const char *from_path, const char *to_path,
|
||||||
Attrib *a, int preserve_flag);
|
Attrib *a, int preserve_flag);
|
||||||
|
|
||||||
|
@ -178,7 +177,7 @@ do_crossload(struct sftp_conn *from, struct sftp_conn *to,
|
||||||
* Recursively download a directory from 'from_path' from the 'from'
|
* Recursively download a directory from 'from_path' from the 'from'
|
||||||
* connection and upload it to 'to' connection at 'to_path'.
|
* connection and upload it to 'to' connection at 'to_path'.
|
||||||
*/
|
*/
|
||||||
int crossload_dir(struct sftp_conn *from, struct sftp_conn *to,
|
int sftp_crossload_dir(struct sftp_conn *from, struct sftp_conn *to,
|
||||||
const char *from_path, const char *to_path,
|
const char *from_path, const char *to_path,
|
||||||
Attrib *dirattrib, int preserve_flag, int print_flag,
|
Attrib *dirattrib, int preserve_flag, int print_flag,
|
||||||
int follow_link_flag);
|
int follow_link_flag);
|
||||||
|
@ -186,26 +185,23 @@ int crossload_dir(struct sftp_conn *from, struct sftp_conn *to,
|
||||||
/*
|
/*
|
||||||
* User/group ID to name translation.
|
* User/group ID to name translation.
|
||||||
*/
|
*/
|
||||||
int can_get_users_groups_by_id(struct sftp_conn *conn);
|
int sftp_can_get_users_groups_by_id(struct sftp_conn *conn);
|
||||||
int do_get_users_groups_by_id(struct sftp_conn *conn,
|
int sftp_get_users_groups_by_id(struct sftp_conn *conn,
|
||||||
const u_int *uids, u_int nuids,
|
const u_int *uids, u_int nuids,
|
||||||
const u_int *gids, u_int ngids,
|
const u_int *gids, u_int ngids,
|
||||||
char ***usernamesp, char ***groupnamesp);
|
char ***usernamesp, char ***groupnamesp);
|
||||||
|
|
||||||
/* Concatenate paths, taking care of slashes. Caller must free result. */
|
/* Concatenate paths, taking care of slashes. Caller must free result. */
|
||||||
char *path_append(const char *, const char *);
|
char *sftp_path_append(const char *, const char *);
|
||||||
|
|
||||||
/* Make absolute path if relative path and CWD is given. Does not modify
|
/* Make absolute path if relative path and CWD is given. Does not modify
|
||||||
* original if the path is already absolute. */
|
* original if the path is already absolute. */
|
||||||
char *make_absolute(char *, const char *);
|
char *sftp_make_absolute(char *, const char *);
|
||||||
|
|
||||||
/* Check if remote path is directory */
|
/* Check if remote path is directory */
|
||||||
int remote_is_dir(struct sftp_conn *conn, const char *path);
|
int sftp_remote_is_dir(struct sftp_conn *conn, const char *path);
|
||||||
|
|
||||||
/* Check if local path is directory */
|
|
||||||
int local_is_dir(const char *path);
|
|
||||||
|
|
||||||
/* Check whether path returned from glob(..., GLOB_MARK, ...) is a directory */
|
/* Check whether path returned from glob(..., GLOB_MARK, ...) is a directory */
|
||||||
int globpath_is_dir(const char *pathname);
|
int sftp_globpath_is_dir(const char *pathname);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
24
sftp-glob.c
24
sftp-glob.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: sftp-glob.c,v 1.31 2022/10/24 21:51:55 djm Exp $ */
|
/* $OpenBSD: sftp-glob.c,v 1.32 2023/09/08 05:56:13 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
|
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
|
||||||
*
|
*
|
||||||
|
@ -51,7 +51,7 @@ fudge_opendir(const char *path)
|
||||||
|
|
||||||
r = xcalloc(1, sizeof(*r));
|
r = xcalloc(1, sizeof(*r));
|
||||||
|
|
||||||
if (do_readdir(cur.conn, path, &r->dir)) {
|
if (sftp_readdir(cur.conn, path, &r->dir)) {
|
||||||
free(r);
|
free(r);
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
@ -103,32 +103,32 @@ fudge_readdir(struct SFTP_OPENDIR *od)
|
||||||
static void
|
static void
|
||||||
fudge_closedir(struct SFTP_OPENDIR *od)
|
fudge_closedir(struct SFTP_OPENDIR *od)
|
||||||
{
|
{
|
||||||
free_sftp_dirents(od->dir);
|
sftp_free_dirents(od->dir);
|
||||||
free(od);
|
free(od);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
fudge_lstat(const char *path, struct stat *st)
|
fudge_lstat(const char *path, struct stat *st)
|
||||||
{
|
{
|
||||||
Attrib *a;
|
Attrib a;
|
||||||
|
|
||||||
if (!(a = do_lstat(cur.conn, path, 1)))
|
if (sftp_lstat(cur.conn, path, 1, &a) != 0)
|
||||||
return(-1);
|
return -1;
|
||||||
|
|
||||||
attrib_to_stat(a, st);
|
attrib_to_stat(&a, st);
|
||||||
|
|
||||||
return(0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
fudge_stat(const char *path, struct stat *st)
|
fudge_stat(const char *path, struct stat *st)
|
||||||
{
|
{
|
||||||
Attrib *a;
|
Attrib a;
|
||||||
|
|
||||||
if (!(a = do_stat(cur.conn, path, 1)))
|
if (sftp_stat(cur.conn, path, 1, &a) != 0)
|
||||||
return(-1);
|
return -1;
|
||||||
|
|
||||||
attrib_to_stat(a, st);
|
attrib_to_stat(&a, st);
|
||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,9 +106,9 @@ lookup_and_record(struct sftp_conn *conn,
|
||||||
u_int i;
|
u_int i;
|
||||||
char **usernames = NULL, **groupnames = NULL;
|
char **usernames = NULL, **groupnames = NULL;
|
||||||
|
|
||||||
if ((r = do_get_users_groups_by_id(conn, uids, nuids, gids, ngids,
|
if ((r = sftp_get_users_groups_by_id(conn, uids, nuids, gids, ngids,
|
||||||
&usernames, &groupnames)) != 0) {
|
&usernames, &groupnames)) != 0) {
|
||||||
debug_fr(r, "do_get_users_groups_by_id");
|
debug_fr(r, "sftp_get_users_groups_by_id");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (i = 0; i < nuids; i++) {
|
for (i = 0; i < nuids; i++) {
|
||||||
|
@ -176,7 +176,7 @@ get_remote_user_groups_from_glob(struct sftp_conn *conn, glob_t *g)
|
||||||
{
|
{
|
||||||
u_int *uids = NULL, nuids = 0, *gids = NULL, ngids = 0;
|
u_int *uids = NULL, nuids = 0, *gids = NULL, ngids = 0;
|
||||||
|
|
||||||
if (!can_get_users_groups_by_id(conn))
|
if (!sftp_can_get_users_groups_by_id(conn))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
collect_ids_from_glob(g, 1, &uids, &nuids);
|
collect_ids_from_glob(g, 1, &uids, &nuids);
|
||||||
|
@ -215,7 +215,7 @@ get_remote_user_groups_from_dirents(struct sftp_conn *conn, SFTP_DIRENT **d)
|
||||||
{
|
{
|
||||||
u_int *uids = NULL, nuids = 0, *gids = NULL, ngids = 0;
|
u_int *uids = NULL, nuids = 0, *gids = NULL, ngids = 0;
|
||||||
|
|
||||||
if (!can_get_users_groups_by_id(conn))
|
if (!sftp_can_get_users_groups_by_id(conn))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
collect_ids_from_dirents(d, 1, &uids, &nuids);
|
collect_ids_from_dirents(d, 1, &uids, &nuids);
|
||||||
|
|
124
sftp.c
124
sftp.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: sftp.c,v 1.234 2023/04/12 08:53:54 jsg Exp $ */
|
/* $OpenBSD: sftp.c,v 1.235 2023/09/08 05:56:13 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
|
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
|
||||||
*
|
*
|
||||||
|
@ -628,11 +628,21 @@ make_absolute_pwd_glob(char *p, const char *pwd)
|
||||||
escpwd = escape_glob(pwd);
|
escpwd = escape_glob(pwd);
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
return escpwd;
|
return escpwd;
|
||||||
ret = make_absolute(p, escpwd);
|
ret = sftp_make_absolute(p, escpwd);
|
||||||
free(escpwd);
|
free(escpwd);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
local_is_dir(const char *path)
|
||||||
|
{
|
||||||
|
struct stat sb;
|
||||||
|
|
||||||
|
if (stat(path, &sb) == -1)
|
||||||
|
return 0;
|
||||||
|
return S_ISDIR(sb.st_mode);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
process_get(struct sftp_conn *conn, const char *src, const char *dst,
|
process_get(struct sftp_conn *conn, const char *src, const char *dst,
|
||||||
const char *pwd, int pflag, int rflag, int resume, int fflag)
|
const char *pwd, int pflag, int rflag, int resume, int fflag)
|
||||||
|
@ -677,12 +687,12 @@ process_get(struct sftp_conn *conn, const char *src, const char *dst,
|
||||||
|
|
||||||
if (g.gl_matchc == 1 && dst) {
|
if (g.gl_matchc == 1 && dst) {
|
||||||
if (local_is_dir(dst)) {
|
if (local_is_dir(dst)) {
|
||||||
abs_dst = path_append(dst, filename);
|
abs_dst = sftp_path_append(dst, filename);
|
||||||
} else {
|
} else {
|
||||||
abs_dst = xstrdup(dst);
|
abs_dst = xstrdup(dst);
|
||||||
}
|
}
|
||||||
} else if (dst) {
|
} else if (dst) {
|
||||||
abs_dst = path_append(dst, filename);
|
abs_dst = sftp_path_append(dst, filename);
|
||||||
} else {
|
} else {
|
||||||
abs_dst = xstrdup(filename);
|
abs_dst = xstrdup(filename);
|
||||||
}
|
}
|
||||||
|
@ -696,13 +706,14 @@ process_get(struct sftp_conn *conn, const char *src, const char *dst,
|
||||||
mprintf("Fetching %s to %s\n",
|
mprintf("Fetching %s to %s\n",
|
||||||
g.gl_pathv[i], abs_dst);
|
g.gl_pathv[i], abs_dst);
|
||||||
/* XXX follow link flag */
|
/* XXX follow link flag */
|
||||||
if (globpath_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
|
if (sftp_globpath_is_dir(g.gl_pathv[i]) &&
|
||||||
if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL,
|
(rflag || global_rflag)) {
|
||||||
pflag || global_pflag, 1, resume,
|
if (sftp_download_dir(conn, g.gl_pathv[i], abs_dst,
|
||||||
|
NULL, pflag || global_pflag, 1, resume,
|
||||||
fflag || global_fflag, 0, 0) == -1)
|
fflag || global_fflag, 0, 0) == -1)
|
||||||
err = -1;
|
err = -1;
|
||||||
} else {
|
} else {
|
||||||
if (do_download(conn, g.gl_pathv[i], abs_dst, NULL,
|
if (sftp_download(conn, g.gl_pathv[i], abs_dst, NULL,
|
||||||
pflag || global_pflag, resume,
|
pflag || global_pflag, resume,
|
||||||
fflag || global_fflag, 0) == -1)
|
fflag || global_fflag, 0) == -1)
|
||||||
err = -1;
|
err = -1;
|
||||||
|
@ -731,7 +742,7 @@ process_put(struct sftp_conn *conn, const char *src, const char *dst,
|
||||||
|
|
||||||
if (dst) {
|
if (dst) {
|
||||||
tmp_dst = xstrdup(dst);
|
tmp_dst = xstrdup(dst);
|
||||||
tmp_dst = make_absolute(tmp_dst, pwd);
|
tmp_dst = sftp_make_absolute(tmp_dst, pwd);
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&g, 0, sizeof(g));
|
memset(&g, 0, sizeof(g));
|
||||||
|
@ -744,7 +755,7 @@ process_put(struct sftp_conn *conn, const char *src, const char *dst,
|
||||||
|
|
||||||
/* If we aren't fetching to pwd then stash this status for later */
|
/* If we aren't fetching to pwd then stash this status for later */
|
||||||
if (tmp_dst != NULL)
|
if (tmp_dst != NULL)
|
||||||
dst_is_dir = remote_is_dir(conn, tmp_dst);
|
dst_is_dir = sftp_remote_is_dir(conn, tmp_dst);
|
||||||
|
|
||||||
/* If multiple matches, dst may be directory or unspecified */
|
/* If multiple matches, dst may be directory or unspecified */
|
||||||
if (g.gl_matchc > 1 && tmp_dst && !dst_is_dir) {
|
if (g.gl_matchc > 1 && tmp_dst && !dst_is_dir) {
|
||||||
|
@ -774,13 +785,13 @@ process_put(struct sftp_conn *conn, const char *src, const char *dst,
|
||||||
if (g.gl_matchc == 1 && tmp_dst) {
|
if (g.gl_matchc == 1 && tmp_dst) {
|
||||||
/* If directory specified, append filename */
|
/* If directory specified, append filename */
|
||||||
if (dst_is_dir)
|
if (dst_is_dir)
|
||||||
abs_dst = path_append(tmp_dst, filename);
|
abs_dst = sftp_path_append(tmp_dst, filename);
|
||||||
else
|
else
|
||||||
abs_dst = xstrdup(tmp_dst);
|
abs_dst = xstrdup(tmp_dst);
|
||||||
} else if (tmp_dst) {
|
} else if (tmp_dst) {
|
||||||
abs_dst = path_append(tmp_dst, filename);
|
abs_dst = sftp_path_append(tmp_dst, filename);
|
||||||
} else {
|
} else {
|
||||||
abs_dst = make_absolute(xstrdup(filename), pwd);
|
abs_dst = sftp_make_absolute(xstrdup(filename), pwd);
|
||||||
}
|
}
|
||||||
free(tmp);
|
free(tmp);
|
||||||
|
|
||||||
|
@ -792,13 +803,14 @@ process_put(struct sftp_conn *conn, const char *src, const char *dst,
|
||||||
mprintf("Uploading %s to %s\n",
|
mprintf("Uploading %s to %s\n",
|
||||||
g.gl_pathv[i], abs_dst);
|
g.gl_pathv[i], abs_dst);
|
||||||
/* XXX follow_link_flag */
|
/* XXX follow_link_flag */
|
||||||
if (globpath_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
|
if (sftp_globpath_is_dir(g.gl_pathv[i]) &&
|
||||||
if (upload_dir(conn, g.gl_pathv[i], abs_dst,
|
(rflag || global_rflag)) {
|
||||||
|
if (sftp_upload_dir(conn, g.gl_pathv[i], abs_dst,
|
||||||
pflag || global_pflag, 1, resume,
|
pflag || global_pflag, 1, resume,
|
||||||
fflag || global_fflag, 0, 0) == -1)
|
fflag || global_fflag, 0, 0) == -1)
|
||||||
err = -1;
|
err = -1;
|
||||||
} else {
|
} else {
|
||||||
if (do_upload(conn, g.gl_pathv[i], abs_dst,
|
if (sftp_upload(conn, g.gl_pathv[i], abs_dst,
|
||||||
pflag || global_pflag, resume,
|
pflag || global_pflag, resume,
|
||||||
fflag || global_fflag, 0) == -1)
|
fflag || global_fflag, 0) == -1)
|
||||||
err = -1;
|
err = -1;
|
||||||
|
@ -839,7 +851,7 @@ do_ls_dir(struct sftp_conn *conn, const char *path,
|
||||||
u_int c = 1, colspace = 0, columns = 1;
|
u_int c = 1, colspace = 0, columns = 1;
|
||||||
SFTP_DIRENT **d;
|
SFTP_DIRENT **d;
|
||||||
|
|
||||||
if ((n = do_readdir(conn, path, &d)) != 0)
|
if ((n = sftp_readdir(conn, path, &d)) != 0)
|
||||||
return (n);
|
return (n);
|
||||||
|
|
||||||
if (!(lflag & LS_SHORT_VIEW)) {
|
if (!(lflag & LS_SHORT_VIEW)) {
|
||||||
|
@ -881,13 +893,13 @@ do_ls_dir(struct sftp_conn *conn, const char *path,
|
||||||
if (d[n]->filename[0] == '.' && !(lflag & LS_SHOW_ALL))
|
if (d[n]->filename[0] == '.' && !(lflag & LS_SHOW_ALL))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
tmp = path_append(path, d[n]->filename);
|
tmp = sftp_path_append(path, d[n]->filename);
|
||||||
fname = path_strip(tmp, strip_path);
|
fname = path_strip(tmp, strip_path);
|
||||||
free(tmp);
|
free(tmp);
|
||||||
|
|
||||||
if (lflag & LS_LONG_VIEW) {
|
if (lflag & LS_LONG_VIEW) {
|
||||||
if ((lflag & (LS_NUMERIC_VIEW|LS_SI_UNITS)) != 0 ||
|
if ((lflag & (LS_NUMERIC_VIEW|LS_SI_UNITS)) != 0 ||
|
||||||
can_get_users_groups_by_id(conn)) {
|
sftp_can_get_users_groups_by_id(conn)) {
|
||||||
char *lname;
|
char *lname;
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
|
|
||||||
|
@ -916,7 +928,7 @@ do_ls_dir(struct sftp_conn *conn, const char *path,
|
||||||
if (!(lflag & LS_LONG_VIEW) && (c != 1))
|
if (!(lflag & LS_LONG_VIEW) && (c != 1))
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
free_sftp_dirents(d);
|
sftp_free_dirents(d);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1070,7 +1082,7 @@ do_df(struct sftp_conn *conn, const char *path, int hflag, int iflag)
|
||||||
char s_root[FMT_SCALED_STRSIZE], s_total[FMT_SCALED_STRSIZE];
|
char s_root[FMT_SCALED_STRSIZE], s_total[FMT_SCALED_STRSIZE];
|
||||||
char s_icapacity[16], s_dcapacity[16];
|
char s_icapacity[16], s_dcapacity[16];
|
||||||
|
|
||||||
if (do_statvfs(conn, path, &st, 1) == -1)
|
if (sftp_statvfs(conn, path, &st, 1) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
if (st.f_files == 0)
|
if (st.f_files == 0)
|
||||||
strlcpy(s_icapacity, "ERR", sizeof(s_icapacity));
|
strlcpy(s_icapacity, "ERR", sizeof(s_icapacity));
|
||||||
|
@ -1544,7 +1556,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
|
||||||
int lflag = 0, pflag = 0, rflag = 0, sflag = 0;
|
int lflag = 0, pflag = 0, rflag = 0, sflag = 0;
|
||||||
int cmdnum, i;
|
int cmdnum, i;
|
||||||
unsigned long n_arg = 0;
|
unsigned long n_arg = 0;
|
||||||
Attrib a, *aa;
|
Attrib a, aa;
|
||||||
char path_buf[PATH_MAX];
|
char path_buf[PATH_MAX];
|
||||||
int err = 0;
|
int err = 0;
|
||||||
glob_t g;
|
glob_t g;
|
||||||
|
@ -1585,23 +1597,24 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
|
||||||
rflag, aflag, fflag);
|
rflag, aflag, fflag);
|
||||||
break;
|
break;
|
||||||
case I_COPY:
|
case I_COPY:
|
||||||
path1 = make_absolute(path1, *pwd);
|
path1 = sftp_make_absolute(path1, *pwd);
|
||||||
path2 = make_absolute(path2, *pwd);
|
path2 = sftp_make_absolute(path2, *pwd);
|
||||||
err = do_copy(conn, path1, path2);
|
err = sftp_copy(conn, path1, path2);
|
||||||
break;
|
break;
|
||||||
case I_RENAME:
|
case I_RENAME:
|
||||||
path1 = make_absolute(path1, *pwd);
|
path1 = sftp_make_absolute(path1, *pwd);
|
||||||
path2 = make_absolute(path2, *pwd);
|
path2 = sftp_make_absolute(path2, *pwd);
|
||||||
err = do_rename(conn, path1, path2, lflag);
|
err = sftp_rename(conn, path1, path2, lflag);
|
||||||
break;
|
break;
|
||||||
case I_SYMLINK:
|
case I_SYMLINK:
|
||||||
sflag = 1;
|
sflag = 1;
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case I_LINK:
|
case I_LINK:
|
||||||
if (!sflag)
|
if (!sflag)
|
||||||
path1 = make_absolute(path1, *pwd);
|
path1 = sftp_make_absolute(path1, *pwd);
|
||||||
path2 = make_absolute(path2, *pwd);
|
path2 = sftp_make_absolute(path2, *pwd);
|
||||||
err = (sflag ? do_symlink : do_hardlink)(conn, path1, path2);
|
err = (sflag ? sftp_symlink : sftp_hardlink)(conn,
|
||||||
|
path1, path2);
|
||||||
break;
|
break;
|
||||||
case I_RM:
|
case I_RM:
|
||||||
path1 = make_absolute_pwd_glob(path1, *pwd);
|
path1 = make_absolute_pwd_glob(path1, *pwd);
|
||||||
|
@ -1609,42 +1622,42 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
|
||||||
for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
|
for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
mprintf("Removing %s\n", g.gl_pathv[i]);
|
mprintf("Removing %s\n", g.gl_pathv[i]);
|
||||||
err = do_rm(conn, g.gl_pathv[i]);
|
err = sftp_rm(conn, g.gl_pathv[i]);
|
||||||
if (err != 0 && err_abort)
|
if (err != 0 && err_abort)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case I_MKDIR:
|
case I_MKDIR:
|
||||||
path1 = make_absolute(path1, *pwd);
|
path1 = sftp_make_absolute(path1, *pwd);
|
||||||
attrib_clear(&a);
|
attrib_clear(&a);
|
||||||
a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
|
a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
|
||||||
a.perm = 0777;
|
a.perm = 0777;
|
||||||
err = do_mkdir(conn, path1, &a, 1);
|
err = sftp_mkdir(conn, path1, &a, 1);
|
||||||
break;
|
break;
|
||||||
case I_RMDIR:
|
case I_RMDIR:
|
||||||
path1 = make_absolute(path1, *pwd);
|
path1 = sftp_make_absolute(path1, *pwd);
|
||||||
err = do_rmdir(conn, path1);
|
err = sftp_rmdir(conn, path1);
|
||||||
break;
|
break;
|
||||||
case I_CHDIR:
|
case I_CHDIR:
|
||||||
if (path1 == NULL || *path1 == '\0')
|
if (path1 == NULL || *path1 == '\0')
|
||||||
path1 = xstrdup(startdir);
|
path1 = xstrdup(startdir);
|
||||||
path1 = make_absolute(path1, *pwd);
|
path1 = sftp_make_absolute(path1, *pwd);
|
||||||
if ((tmp = do_realpath(conn, path1)) == NULL) {
|
if ((tmp = sftp_realpath(conn, path1)) == NULL) {
|
||||||
err = 1;
|
err = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ((aa = do_stat(conn, tmp, 0)) == NULL) {
|
if (sftp_stat(conn, tmp, 0, &aa) != 0) {
|
||||||
free(tmp);
|
free(tmp);
|
||||||
err = 1;
|
err = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!(aa->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) {
|
if (!(aa.flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) {
|
||||||
error("Can't change directory: Can't check target");
|
error("Can't change directory: Can't check target");
|
||||||
free(tmp);
|
free(tmp);
|
||||||
err = 1;
|
err = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!S_ISDIR(aa->perm)) {
|
if (!S_ISDIR(aa.perm)) {
|
||||||
error("Can't change directory: \"%s\" is not "
|
error("Can't change directory: \"%s\" is not "
|
||||||
"a directory", tmp);
|
"a directory", tmp);
|
||||||
free(tmp);
|
free(tmp);
|
||||||
|
@ -1672,7 +1685,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
|
||||||
/* Default to current directory if no path specified */
|
/* Default to current directory if no path specified */
|
||||||
if (path1 == NULL)
|
if (path1 == NULL)
|
||||||
path1 = xstrdup(*pwd);
|
path1 = xstrdup(*pwd);
|
||||||
path1 = make_absolute(path1, *pwd);
|
path1 = sftp_make_absolute(path1, *pwd);
|
||||||
err = do_df(conn, path1, hflag, iflag);
|
err = do_df(conn, path1, hflag, iflag);
|
||||||
break;
|
break;
|
||||||
case I_LCHDIR:
|
case I_LCHDIR:
|
||||||
|
@ -1714,7 +1727,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
mprintf("Changing mode on %s\n",
|
mprintf("Changing mode on %s\n",
|
||||||
g.gl_pathv[i]);
|
g.gl_pathv[i]);
|
||||||
err = (hflag ? do_lsetstat : do_setstat)(conn,
|
err = (hflag ? sftp_lsetstat : sftp_setstat)(conn,
|
||||||
g.gl_pathv[i], &a);
|
g.gl_pathv[i], &a);
|
||||||
if (err != 0 && err_abort)
|
if (err != 0 && err_abort)
|
||||||
break;
|
break;
|
||||||
|
@ -1725,15 +1738,15 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
|
||||||
path1 = make_absolute_pwd_glob(path1, *pwd);
|
path1 = make_absolute_pwd_glob(path1, *pwd);
|
||||||
remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
|
remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
|
||||||
for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
|
for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
|
||||||
if (!(aa = (hflag ? do_lstat : do_stat)(conn,
|
if ((hflag ? sftp_lstat : sftp_stat)(conn,
|
||||||
g.gl_pathv[i], 0))) {
|
g.gl_pathv[i], 0, &aa) != 0) {
|
||||||
if (err_abort) {
|
if (err_abort) {
|
||||||
err = -1;
|
err = -1;
|
||||||
break;
|
break;
|
||||||
} else
|
} else
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) {
|
if (!(aa.flags & SSH2_FILEXFER_ATTR_UIDGID)) {
|
||||||
error("Can't get current ownership of "
|
error("Can't get current ownership of "
|
||||||
"remote file \"%s\"", g.gl_pathv[i]);
|
"remote file \"%s\"", g.gl_pathv[i]);
|
||||||
if (err_abort) {
|
if (err_abort) {
|
||||||
|
@ -1742,20 +1755,20 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
|
||||||
} else
|
} else
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
aa->flags &= SSH2_FILEXFER_ATTR_UIDGID;
|
aa.flags &= SSH2_FILEXFER_ATTR_UIDGID;
|
||||||
if (cmdnum == I_CHOWN) {
|
if (cmdnum == I_CHOWN) {
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
mprintf("Changing owner on %s\n",
|
mprintf("Changing owner on %s\n",
|
||||||
g.gl_pathv[i]);
|
g.gl_pathv[i]);
|
||||||
aa->uid = n_arg;
|
aa.uid = n_arg;
|
||||||
} else {
|
} else {
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
mprintf("Changing group on %s\n",
|
mprintf("Changing group on %s\n",
|
||||||
g.gl_pathv[i]);
|
g.gl_pathv[i]);
|
||||||
aa->gid = n_arg;
|
aa.gid = n_arg;
|
||||||
}
|
}
|
||||||
err = (hflag ? do_lsetstat : do_setstat)(conn,
|
err = (hflag ? sftp_lsetstat : sftp_setstat)(conn,
|
||||||
g.gl_pathv[i], aa);
|
g.gl_pathv[i], &aa);
|
||||||
if (err != 0 && err_abort)
|
if (err != 0 && err_abort)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2234,16 +2247,15 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
|
||||||
}
|
}
|
||||||
#endif /* USE_LIBEDIT */
|
#endif /* USE_LIBEDIT */
|
||||||
|
|
||||||
remote_path = do_realpath(conn, ".");
|
if ((remote_path = sftp_realpath(conn, ".")) == NULL)
|
||||||
if (remote_path == NULL)
|
|
||||||
fatal("Need cwd");
|
fatal("Need cwd");
|
||||||
startdir = xstrdup(remote_path);
|
startdir = xstrdup(remote_path);
|
||||||
|
|
||||||
if (file1 != NULL) {
|
if (file1 != NULL) {
|
||||||
dir = xstrdup(file1);
|
dir = xstrdup(file1);
|
||||||
dir = make_absolute(dir, remote_path);
|
dir = sftp_make_absolute(dir, remote_path);
|
||||||
|
|
||||||
if (remote_is_dir(conn, dir) && file2 == NULL) {
|
if (sftp_remote_is_dir(conn, dir) && file2 == NULL) {
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
mprintf("Changing to: %s\n", dir);
|
mprintf("Changing to: %s\n", dir);
|
||||||
snprintf(cmd, sizeof cmd, "cd \"%s\"", dir);
|
snprintf(cmd, sizeof cmd, "cd \"%s\"", dir);
|
||||||
|
@ -2652,7 +2664,7 @@ main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
freeargs(&args);
|
freeargs(&args);
|
||||||
|
|
||||||
conn = do_init(in, out, copy_buffer_len, num_requests, limit_kbps);
|
conn = sftp_init(in, out, copy_buffer_len, num_requests, limit_kbps);
|
||||||
if (conn == NULL)
|
if (conn == NULL)
|
||||||
fatal("Couldn't initialise connection to server");
|
fatal("Couldn't initialise connection to server");
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue