mirror of
git://anongit.mindrot.org/openssh.git
synced 2025-02-16 13:56:52 +00:00
upstream: make scp(1) in SFTP mode follow symlinks like
traditional scp(1) ok markus@ OpenBSD-Commit-ID: 97255e55be37e8e26605e4ba1e69f9781765d231
This commit is contained in:
parent
133b44e500
commit
7b1cbcb759
8
scp.c
8
scp.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: scp.c,v 1.220 2021/08/07 00:08:52 djm Exp $ */
|
||||
/* $OpenBSD: scp.c,v 1.221 2021/08/07 00:12:09 djm Exp $ */
|
||||
/*
|
||||
* scp - secure remote copy. This is basically patched BSD rcp which
|
||||
* uses ssh to do the data transfer (instead of using rcmd).
|
||||
@ -1290,7 +1290,7 @@ source_sftp(int argc, char *src, char *targ,
|
||||
|
||||
if (local_is_dir(src) && iamrecursive) {
|
||||
if (upload_dir(conn, src, abs_dst, pflag,
|
||||
SFTP_PROGRESS_ONLY, 0, 0) != 0) {
|
||||
SFTP_PROGRESS_ONLY, 0, 0, 1) != 0) {
|
||||
fatal("failed to upload directory %s to %s",
|
||||
src, abs_dst);
|
||||
}
|
||||
@ -1522,7 +1522,7 @@ sink_sftp(int argc, char *dst, const char *src, struct sftp_conn *conn)
|
||||
debug("Fetching %s to %s\n", g.gl_pathv[i], abs_dst);
|
||||
if (globpath_is_dir(g.gl_pathv[i]) && iamrecursive) {
|
||||
if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL,
|
||||
pflag, SFTP_PROGRESS_ONLY, 0, 0) == -1)
|
||||
pflag, SFTP_PROGRESS_ONLY, 0, 0, 1) == -1)
|
||||
err = -1;
|
||||
} else {
|
||||
if (do_download(conn, g.gl_pathv[i], abs_dst, NULL,
|
||||
@ -1935,7 +1935,7 @@ throughlocal_sftp(struct sftp_conn *from, struct sftp_conn *to,
|
||||
debug("Fetching %s to %s\n", g.gl_pathv[i], abs_dst);
|
||||
if (globpath_is_dir(g.gl_pathv[i]) && iamrecursive) {
|
||||
if (crossload_dir(from, to, g.gl_pathv[i], abs_dst,
|
||||
NULL, pflag, 1) == -1)
|
||||
NULL, pflag, SFTP_PROGRESS_ONLY, 1) == -1)
|
||||
err = -1;
|
||||
} else {
|
||||
if (do_crossload(from, to, g.gl_pathv[i], abs_dst, NULL,
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: sftp-client.c,v 1.149 2021/08/07 00:10:49 djm Exp $ */
|
||||
/* $OpenBSD: sftp-client.c,v 1.150 2021/08/07 00:12:09 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
|
||||
*
|
||||
@ -1615,7 +1615,7 @@ do_download(struct sftp_conn *conn, const char *remote_path,
|
||||
static int
|
||||
download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
|
||||
int depth, Attrib *dirattrib, int preserve_flag, int print_flag,
|
||||
int resume_flag, int fsync_flag)
|
||||
int resume_flag, int fsync_flag, int follow_link_flag)
|
||||
{
|
||||
int i, ret = 0;
|
||||
SFTP_DIRENT **dir_entries;
|
||||
@ -1671,12 +1671,20 @@ download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
|
||||
continue;
|
||||
if (download_dir_internal(conn, new_src, new_dst,
|
||||
depth + 1, &(dir_entries[i]->a), preserve_flag,
|
||||
print_flag, resume_flag, fsync_flag) == -1)
|
||||
print_flag, resume_flag,
|
||||
fsync_flag, follow_link_flag) == -1)
|
||||
ret = -1;
|
||||
} else if (S_ISREG(dir_entries[i]->a.perm) ) {
|
||||
} else if (S_ISREG(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
|
||||
* Attrib. do_download() will do a FXP_STAT operation
|
||||
* and get the link target's attributes.
|
||||
*/
|
||||
if (do_download(conn, new_src, new_dst,
|
||||
&(dir_entries[i]->a), preserve_flag,
|
||||
resume_flag, fsync_flag) == -1) {
|
||||
S_ISLNK(dir_entries[i]->a.perm) ? NULL :
|
||||
&(dir_entries[i]->a),
|
||||
preserve_flag, resume_flag, fsync_flag) == -1) {
|
||||
error("Download of file %s to %s failed",
|
||||
new_src, new_dst);
|
||||
ret = -1;
|
||||
@ -1714,7 +1722,7 @@ download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
|
||||
int
|
||||
download_dir(struct sftp_conn *conn, const char *src, const char *dst,
|
||||
Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag,
|
||||
int fsync_flag)
|
||||
int fsync_flag, int follow_link_flag)
|
||||
{
|
||||
char *src_canon;
|
||||
int ret;
|
||||
@ -1725,7 +1733,8 @@ download_dir(struct sftp_conn *conn, const char *src, const char *dst,
|
||||
}
|
||||
|
||||
ret = download_dir_internal(conn, src_canon, dst, 0,
|
||||
dirattrib, preserve_flag, print_flag, resume_flag, fsync_flag);
|
||||
dirattrib, preserve_flag, print_flag, resume_flag, fsync_flag,
|
||||
follow_link_flag);
|
||||
free(src_canon);
|
||||
return ret;
|
||||
}
|
||||
@ -1936,7 +1945,8 @@ do_upload(struct sftp_conn *conn, const char *local_path,
|
||||
|
||||
static int
|
||||
upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
|
||||
int depth, int preserve_flag, int print_flag, int resume, int fsync_flag)
|
||||
int depth, int preserve_flag, int print_flag, int resume, int fsync_flag,
|
||||
int follow_link_flag)
|
||||
{
|
||||
int ret = 0;
|
||||
DIR *dirp;
|
||||
@ -2014,9 +2024,10 @@ upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
|
||||
|
||||
if (upload_dir_internal(conn, new_src, new_dst,
|
||||
depth + 1, preserve_flag, print_flag, resume,
|
||||
fsync_flag) == -1)
|
||||
fsync_flag, follow_link_flag) == -1)
|
||||
ret = -1;
|
||||
} else if (S_ISREG(sb.st_mode)) {
|
||||
} else if (S_ISREG(sb.st_mode) ||
|
||||
(follow_link_flag && S_ISLNK(sb.st_mode))) {
|
||||
if (do_upload(conn, new_src, new_dst,
|
||||
preserve_flag, resume, fsync_flag) == -1) {
|
||||
error("Uploading of file %s to %s failed!",
|
||||
@ -2037,7 +2048,8 @@ upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
|
||||
|
||||
int
|
||||
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)
|
||||
{
|
||||
char *dst_canon;
|
||||
int ret;
|
||||
@ -2048,7 +2060,7 @@ upload_dir(struct sftp_conn *conn, const char *src, const char *dst,
|
||||
}
|
||||
|
||||
ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag,
|
||||
print_flag, resume, fsync_flag);
|
||||
print_flag, resume, fsync_flag, follow_link_flag);
|
||||
|
||||
free(dst_canon);
|
||||
return ret;
|
||||
@ -2372,7 +2384,8 @@ do_crossload(struct sftp_conn *from, struct sftp_conn *to,
|
||||
static int
|
||||
crossload_dir_internal(struct sftp_conn *from, struct sftp_conn *to,
|
||||
const char *from_path, const char *to_path,
|
||||
int depth, Attrib *dirattrib, int preserve_flag, int print_flag)
|
||||
int depth, Attrib *dirattrib, int preserve_flag, int print_flag,
|
||||
int follow_link_flag)
|
||||
{
|
||||
int i, ret = 0;
|
||||
SFTP_DIRENT **dir_entries;
|
||||
@ -2394,7 +2407,7 @@ crossload_dir_internal(struct sftp_conn *from, struct sftp_conn *to,
|
||||
error("\"%s\" is not a directory", from_path);
|
||||
return -1;
|
||||
}
|
||||
if (print_flag)
|
||||
if (print_flag && print_flag != SFTP_PROGRESS_ONLY)
|
||||
mprintf("Retrieving %s\n", from_path);
|
||||
|
||||
curdir = *dirattrib; /* dirattrib will be clobbered */
|
||||
@ -2446,10 +2459,17 @@ crossload_dir_internal(struct sftp_conn *from, struct sftp_conn *to,
|
||||
if (crossload_dir_internal(from, to,
|
||||
new_from_path, new_to_path,
|
||||
depth + 1, &(dir_entries[i]->a), preserve_flag,
|
||||
print_flag) == -1)
|
||||
print_flag, follow_link_flag) == -1)
|
||||
ret = -1;
|
||||
} else if (S_ISREG(dir_entries[i]->a.perm) ) {
|
||||
} else if (S_ISREG(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
|
||||
* Attrib. do_download() will do a FXP_STAT operation
|
||||
* and get the link target's attributes.
|
||||
*/
|
||||
if (do_crossload(from, to, new_from_path, new_to_path,
|
||||
S_ISLNK(dir_entries[i]->a.perm) ? NULL :
|
||||
&(dir_entries[i]->a), preserve_flag) == -1) {
|
||||
error("Transfer of file %s to %s failed",
|
||||
new_from_path, new_to_path);
|
||||
@ -2472,7 +2492,7 @@ crossload_dir_internal(struct sftp_conn *from, struct sftp_conn *to,
|
||||
int
|
||||
crossload_dir(struct sftp_conn *from, struct sftp_conn *to,
|
||||
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)
|
||||
{
|
||||
char *from_path_canon;
|
||||
int ret;
|
||||
@ -2483,7 +2503,7 @@ crossload_dir(struct sftp_conn *from, struct sftp_conn *to,
|
||||
}
|
||||
|
||||
ret = crossload_dir_internal(from, to, from_path_canon, to_path, 0,
|
||||
dirattrib, preserve_flag, print_flag);
|
||||
dirattrib, preserve_flag, print_flag, follow_link_flag);
|
||||
free(from_path_canon);
|
||||
return ret;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: sftp-client.h,v 1.32 2021/08/07 00:08:52 djm Exp $ */
|
||||
/* $OpenBSD: sftp-client.h,v 1.33 2021/08/07 00:12:09 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
|
||||
@ -140,7 +140,7 @@ int do_download(struct sftp_conn *, const char *, const char *,
|
||||
* times if 'pflag' is set
|
||||
*/
|
||||
int download_dir(struct sftp_conn *, const char *, const char *,
|
||||
Attrib *, int, int, int, int);
|
||||
Attrib *, int, int, int, int, int);
|
||||
|
||||
/*
|
||||
* Upload 'local_path' to 'remote_path'. Preserve permissions and times
|
||||
@ -153,7 +153,7 @@ int do_upload(struct sftp_conn *, const char *, const char *, int, int, int);
|
||||
* times if 'pflag' is set
|
||||
*/
|
||||
int upload_dir(struct sftp_conn *, const char *, const char *, int, int, int,
|
||||
int);
|
||||
int, int);
|
||||
|
||||
/*
|
||||
* Download a 'from_path' from the 'from' connection and upload it to
|
||||
@ -170,7 +170,8 @@ do_crossload(struct sftp_conn *from, struct sftp_conn *to,
|
||||
*/
|
||||
int crossload_dir(struct sftp_conn *from, struct sftp_conn *to,
|
||||
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);
|
||||
|
||||
/* Concatenate paths, taking care of slashes. Caller must free result. */
|
||||
char *path_append(const char *, const char *);
|
||||
|
8
sftp.c
8
sftp.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: sftp.c,v 1.209 2021/04/03 06:58:30 djm Exp $ */
|
||||
/* $OpenBSD: sftp.c,v 1.210 2021/08/07 00:12:09 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
|
||||
*
|
||||
@ -655,10 +655,11 @@ process_get(struct sftp_conn *conn, const char *src, const char *dst,
|
||||
else if (!quiet && !resume)
|
||||
mprintf("Fetching %s to %s\n",
|
||||
g.gl_pathv[i], abs_dst);
|
||||
/* XXX follow link flag */
|
||||
if (globpath_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
|
||||
if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL,
|
||||
pflag || global_pflag, 1, resume,
|
||||
fflag || global_fflag) == -1)
|
||||
fflag || global_fflag, 0) == -1)
|
||||
err = -1;
|
||||
} else {
|
||||
if (do_download(conn, g.gl_pathv[i], abs_dst, NULL,
|
||||
@ -748,10 +749,11 @@ process_put(struct sftp_conn *conn, const char *src, const char *dst,
|
||||
else if (!quiet && !resume)
|
||||
mprintf("Uploading %s to %s\n",
|
||||
g.gl_pathv[i], abs_dst);
|
||||
/* XXX follow_link_flag */
|
||||
if (globpath_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
|
||||
if (upload_dir(conn, g.gl_pathv[i], abs_dst,
|
||||
pflag || global_pflag, 1, resume,
|
||||
fflag || global_fflag) == -1)
|
||||
fflag || global_fflag, 0) == -1)
|
||||
err = -1;
|
||||
} else {
|
||||
if (do_upload(conn, g.gl_pathv[i], abs_dst,
|
||||
|
Loading…
Reference in New Issue
Block a user