version 1.160, 2022/01/08 07:37:32 |
version 1.161, 2022/01/17 21:41:04 |
|
|
if ((r = sshbuf_get_u32(msg, &status)) != 0) |
if ((r = sshbuf_get_u32(msg, &status)) != 0) |
fatal_fr(r, "parse status"); |
fatal_fr(r, "parse status"); |
if (quiet) |
if (quiet) |
debug("Couldn't stat remote file: %s", fx2txt(status)); |
debug("stat remote: %s", fx2txt(status)); |
else |
else |
error("Couldn't stat remote file: %s", fx2txt(status)); |
error("stat remote: %s", fx2txt(status)); |
sshbuf_free(msg); |
sshbuf_free(msg); |
return(NULL); |
return(NULL); |
} else if (type != SSH2_FXP_ATTRS) { |
} else if (type != SSH2_FXP_ATTRS) { |
|
|
if ((r = sshbuf_get_u32(msg, &status)) != 0) |
if ((r = sshbuf_get_u32(msg, &status)) != 0) |
fatal_fr(r, "parse status"); |
fatal_fr(r, "parse status"); |
if (quiet) |
if (quiet) |
debug("Couldn't statvfs: %s", fx2txt(status)); |
debug("remote statvfs: %s", fx2txt(status)); |
else |
else |
error("Couldn't statvfs: %s", fx2txt(status)); |
error("remote statvfs: %s", fx2txt(status)); |
sshbuf_free(msg); |
sshbuf_free(msg); |
return -1; |
return -1; |
} else if (type != SSH2_FXP_EXTENDED_REPLY) { |
} else if (type != SSH2_FXP_EXTENDED_REPLY) { |
|
|
|
|
status = get_status(conn, id); |
status = get_status(conn, id); |
if (status != SSH2_FX_OK) |
if (status != SSH2_FX_OK) |
error("Couldn't close file: %s", fx2txt(status)); |
error("close remote: %s", fx2txt(status)); |
|
|
sshbuf_free(msg); |
sshbuf_free(msg); |
|
|
|
|
send_string_request(conn, id, SSH2_FXP_REMOVE, path, strlen(path)); |
send_string_request(conn, id, SSH2_FXP_REMOVE, path, strlen(path)); |
status = get_status(conn, id); |
status = get_status(conn, id); |
if (status != SSH2_FX_OK) |
if (status != SSH2_FX_OK) |
error("Couldn't delete file: %s", fx2txt(status)); |
error("remote delete %s: %s", path, fx2txt(status)); |
return status == SSH2_FX_OK ? 0 : -1; |
return status == SSH2_FX_OK ? 0 : -1; |
} |
} |
|
|
|
|
{ |
{ |
u_int status, id; |
u_int status, id; |
|
|
|
debug2("Sending SSH2_FXP_MKDIR \"%s\"", path); |
|
|
id = conn->msg_id++; |
id = conn->msg_id++; |
send_string_attrs_request(conn, id, SSH2_FXP_MKDIR, path, |
send_string_attrs_request(conn, id, SSH2_FXP_MKDIR, path, |
strlen(path), a); |
strlen(path), a); |
|
|
status = get_status(conn, id); |
status = get_status(conn, id); |
if (status != SSH2_FX_OK && print_flag) |
if (status != SSH2_FX_OK && print_flag) |
error("Couldn't create directory: %s", fx2txt(status)); |
error("remote mkdir \"%s\": %s", path, fx2txt(status)); |
|
|
return status == SSH2_FX_OK ? 0 : -1; |
return status == SSH2_FX_OK ? 0 : -1; |
} |
} |
|
|
{ |
{ |
u_int status, id; |
u_int status, id; |
|
|
|
debug2("Sending SSH2_FXP_RMDIR \"%s\"", path); |
|
|
id = conn->msg_id++; |
id = conn->msg_id++; |
send_string_request(conn, id, SSH2_FXP_RMDIR, path, |
send_string_request(conn, id, SSH2_FXP_RMDIR, path, |
strlen(path)); |
strlen(path)); |
|
|
status = get_status(conn, id); |
status = get_status(conn, id); |
if (status != SSH2_FX_OK) |
if (status != SSH2_FX_OK) |
error("Couldn't remove directory: %s", fx2txt(status)); |
error("remote rmdir \"%s\": %s", path, fx2txt(status)); |
|
|
return status == SSH2_FX_OK ? 0 : -1; |
return status == SSH2_FX_OK ? 0 : -1; |
} |
} |
|
|
{ |
{ |
u_int id; |
u_int id; |
|
|
|
debug2("Sending SSH2_FXP_STAT \"%s\"", path); |
|
|
id = conn->msg_id++; |
id = conn->msg_id++; |
|
|
send_string_request(conn, id, |
send_string_request(conn, id, |
|
|
{ |
{ |
u_int id; |
u_int id; |
|
|
|
debug2("Sending SSH2_FXP_FSTAT \"%s\""); |
|
|
id = conn->msg_id++; |
id = conn->msg_id++; |
send_string_request(conn, id, SSH2_FXP_FSTAT, handle, |
send_string_request(conn, id, SSH2_FXP_FSTAT, handle, |
handle_len); |
handle_len); |
|
|
{ |
{ |
u_int status, id; |
u_int status, id; |
|
|
|
debug2("Sending SSH2_FXP_SETSTAT \"%s\"", path); |
|
|
id = conn->msg_id++; |
id = conn->msg_id++; |
send_string_attrs_request(conn, id, SSH2_FXP_SETSTAT, path, |
send_string_attrs_request(conn, id, SSH2_FXP_SETSTAT, path, |
strlen(path), a); |
strlen(path), a); |
|
|
status = get_status(conn, id); |
status = get_status(conn, id); |
if (status != SSH2_FX_OK) |
if (status != SSH2_FX_OK) |
error("Couldn't setstat on \"%s\": %s", path, |
error("remote setstat \"%s\": %s", path, fx2txt(status)); |
fx2txt(status)); |
|
|
|
return status == SSH2_FX_OK ? 0 : -1; |
return status == SSH2_FX_OK ? 0 : -1; |
} |
} |
|
|
{ |
{ |
u_int status, id; |
u_int status, id; |
|
|
|
debug2("Sending SSH2_FXP_FSETSTAT"); |
|
|
id = conn->msg_id++; |
id = conn->msg_id++; |
send_string_attrs_request(conn, id, SSH2_FXP_FSETSTAT, handle, |
send_string_attrs_request(conn, id, SSH2_FXP_FSETSTAT, handle, |
handle_len, a); |
handle_len, a); |
|
|
status = get_status(conn, id); |
status = get_status(conn, id); |
if (status != SSH2_FX_OK) |
if (status != SSH2_FX_OK) |
error("Couldn't fsetstat: %s", fx2txt(status)); |
error("remote fsetstat: %s", fx2txt(status)); |
|
|
return status == SSH2_FX_OK ? 0 : -1; |
return status == SSH2_FX_OK ? 0 : -1; |
} |
} |
|
|
|
|
expected_id = id = conn->msg_id++; |
expected_id = id = conn->msg_id++; |
if (expand) { |
if (expand) { |
|
debug2("Sending SSH2_FXP_EXTENDED(expand-path@openssh.com) " |
|
"\"%s\"", path); |
if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || |
if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || |
(r = sshbuf_put_u32(msg, id)) != 0 || |
(r = sshbuf_put_u32(msg, id)) != 0 || |
(r = sshbuf_put_cstring(msg, |
(r = sshbuf_put_cstring(msg, |
|
|
fatal_fr(r, "compose %s", what); |
fatal_fr(r, "compose %s", what); |
send_msg(conn, msg); |
send_msg(conn, msg); |
} else { |
} else { |
|
debug2("Sending SSH2_FXP_REALPATH \"%s\"", path); |
send_string_request(conn, id, SSH2_FXP_REALPATH, |
send_string_request(conn, id, SSH2_FXP_REALPATH, |
path, strlen(path)); |
path, strlen(path)); |
} |
} |
|
|
/* Send rename request */ |
/* Send rename request */ |
id = conn->msg_id++; |
id = conn->msg_id++; |
if (use_ext) { |
if (use_ext) { |
|
debug2("Sending SSH2_FXP_EXTENDED(posix-rename@openssh.com) " |
|
"\"%s\" to \"%s\"", oldpath, newpath); |
if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || |
if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || |
(r = sshbuf_put_u32(msg, id)) != 0 || |
(r = sshbuf_put_u32(msg, id)) != 0 || |
(r = sshbuf_put_cstring(msg, |
(r = sshbuf_put_cstring(msg, |
"posix-rename@openssh.com")) != 0) |
"posix-rename@openssh.com")) != 0) |
fatal_fr(r, "compose posix-rename"); |
fatal_fr(r, "compose posix-rename"); |
} else { |
} else { |
|
debug2("Sending SSH2_FXP_RENAME \"%s\" to \"%s\"", |
|
oldpath, newpath); |
if ((r = sshbuf_put_u8(msg, SSH2_FXP_RENAME)) != 0 || |
if ((r = sshbuf_put_u8(msg, SSH2_FXP_RENAME)) != 0 || |
(r = sshbuf_put_u32(msg, id)) != 0) |
(r = sshbuf_put_u32(msg, id)) != 0) |
fatal_fr(r, "compose rename"); |
fatal_fr(r, "compose rename"); |
|
|
|
|
status = get_status(conn, id); |
status = get_status(conn, id); |
if (status != SSH2_FX_OK) |
if (status != SSH2_FX_OK) |
error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath, |
error("remote rename \"%s\" to \"%s\": %s", oldpath, |
newpath, fx2txt(status)); |
newpath, fx2txt(status)); |
|
|
return status == SSH2_FX_OK ? 0 : -1; |
return status == SSH2_FX_OK ? 0 : -1; |
|
|
error("Server does not support hardlink@openssh.com extension"); |
error("Server does not support hardlink@openssh.com extension"); |
return -1; |
return -1; |
} |
} |
|
debug2("Sending SSH2_FXP_EXTENDED(hardlink@openssh.com) " |
|
"\"%s\" to \"%s\"", oldpath, newpath); |
|
|
if ((msg = sshbuf_new()) == NULL) |
if ((msg = sshbuf_new()) == NULL) |
fatal_f("sshbuf_new failed"); |
fatal_f("sshbuf_new failed"); |
|
|
|
|
status = get_status(conn, id); |
status = get_status(conn, id); |
if (status != SSH2_FX_OK) |
if (status != SSH2_FX_OK) |
error("Couldn't link file \"%s\" to \"%s\": %s", oldpath, |
error("remote link \"%s\" to \"%s\": %s", oldpath, |
newpath, fx2txt(status)); |
newpath, fx2txt(status)); |
|
|
return status == SSH2_FX_OK ? 0 : -1; |
return status == SSH2_FX_OK ? 0 : -1; |
|
|
error("This server does not support the symlink operation"); |
error("This server does not support the symlink operation"); |
return(SSH2_FX_OP_UNSUPPORTED); |
return(SSH2_FX_OP_UNSUPPORTED); |
} |
} |
|
debug2("Sending SSH2_FXP_SYMLINK \"%s\" to \"%s\"", oldpath, newpath); |
|
|
if ((msg = sshbuf_new()) == NULL) |
if ((msg = sshbuf_new()) == NULL) |
fatal_f("sshbuf_new failed"); |
fatal_f("sshbuf_new failed"); |
|
|
|
|
status = get_status(conn, id); |
status = get_status(conn, id); |
if (status != SSH2_FX_OK) |
if (status != SSH2_FX_OK) |
error("Couldn't symlink file \"%s\" to \"%s\": %s", oldpath, |
error("remote symlink file \"%s\" to \"%s\": %s", oldpath, |
newpath, fx2txt(status)); |
newpath, fx2txt(status)); |
|
|
return status == SSH2_FX_OK ? 0 : -1; |
return status == SSH2_FX_OK ? 0 : -1; |
|
|
/* Silently return if the extension is not supported */ |
/* Silently return if the extension is not supported */ |
if ((conn->exts & SFTP_EXT_FSYNC) == 0) |
if ((conn->exts & SFTP_EXT_FSYNC) == 0) |
return -1; |
return -1; |
|
debug2("Sending SSH2_FXP_EXTENDED(fsync@openssh.com)"); |
|
|
/* Send fsync request */ |
/* Send fsync request */ |
if ((msg = sshbuf_new()) == NULL) |
if ((msg = sshbuf_new()) == NULL) |
|
|
|
|
status = get_status(conn, id); |
status = get_status(conn, id); |
if (status != SSH2_FX_OK) |
if (status != SSH2_FX_OK) |
error("Couldn't sync file: %s", fx2txt(status)); |
error("remote fsync: %s", fx2txt(status)); |
|
|
return status == SSH2_FX_OK ? 0 : -1; |
return status == SSH2_FX_OK ? 0 : -1; |
} |
} |
|
|
u_char type; |
u_char type; |
int r; |
int r; |
|
|
|
debug2("Sending SSH2_FXP_READLINK \"%s\"", path); |
|
|
expected_id = id = conn->msg_id++; |
expected_id = id = conn->msg_id++; |
send_string_request(conn, id, SSH2_FXP_READLINK, path, strlen(path)); |
send_string_request(conn, id, SSH2_FXP_READLINK, path, strlen(path)); |
|
|
|
|
return -1; |
return -1; |
} |
} |
|
|
|
debug2("Sending SSH2_FXP_EXTENDED(statvfs@openssh.com) \"%s\"", path); |
|
|
id = conn->msg_id++; |
id = conn->msg_id++; |
|
|
if ((msg = sshbuf_new()) == NULL) |
if ((msg = sshbuf_new()) == NULL) |
|
|
return -1; |
return -1; |
} |
} |
|
|
|
debug2("Sending SSH2_FXP_EXTENDED(fstatvfs@openssh.com)"); |
|
|
id = conn->msg_id++; |
id = conn->msg_id++; |
|
|
if ((msg = sshbuf_new()) == NULL) |
if ((msg = sshbuf_new()) == NULL) |
|
|
return -1; |
return -1; |
} |
} |
|
|
|
debug2("Sending SSH2_FXP_EXTENDED(lsetstat@openssh.com) \"%s\"", path); |
|
|
id = conn->msg_id++; |
id = conn->msg_id++; |
if ((msg = sshbuf_new()) == NULL) |
if ((msg = sshbuf_new()) == NULL) |
fatal_f("sshbuf_new failed"); |
fatal_f("sshbuf_new failed"); |
|
|
|
|
status = get_status(conn, id); |
status = get_status(conn, id); |
if (status != SSH2_FX_OK) |
if (status != SSH2_FX_OK) |
error("Couldn't setstat on \"%s\": %s", path, |
error("remote lsetstat \"%s\": %s", path, fx2txt(status)); |
fx2txt(status)); |
|
|
|
return status == SSH2_FX_OK ? 0 : -1; |
return status == SSH2_FX_OK ? 0 : -1; |
} |
} |
|
|
int r; |
int r; |
u_int id; |
u_int id; |
|
|
|
debug2("Sending SSH2_FXP_OPEN \"%s\"", path); |
|
|
*handlep = NULL; |
*handlep = NULL; |
*handle_lenp = 0; |
*handle_lenp = 0; |
|
|
|
|
struct request *req; |
struct request *req; |
u_char type; |
u_char type; |
|
|
|
debug2_f("download remote \"%s\" to local \"%s\"", |
|
remote_path, local_path); |
|
|
TAILQ_INIT(&requests); |
TAILQ_INIT(&requests); |
|
|
if (a == NULL && (a = do_stat(conn, remote_path, 0)) == NULL) |
if (a == NULL && (a = do_stat(conn, remote_path, 0)) == NULL) |
|
|
|
|
if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && |
if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && |
(!S_ISREG(a->perm))) { |
(!S_ISREG(a->perm))) { |
error("Cannot download non-regular file: %s", remote_path); |
error("download %s: not a regular file", remote_path); |
return(-1); |
return(-1); |
} |
} |
|
|
|
|
local_fd = open(local_path, |
local_fd = open(local_path, |
O_WRONLY | O_CREAT | (resume_flag ? 0 : O_TRUNC), mode | S_IWUSR); |
O_WRONLY | O_CREAT | (resume_flag ? 0 : O_TRUNC), mode | S_IWUSR); |
if (local_fd == -1) { |
if (local_fd == -1) { |
error("Couldn't open local file \"%s\" for writing: %s", |
error("open local \"%s\": %s", local_path, strerror(errno)); |
local_path, strerror(errno)); |
|
goto fail; |
goto fail; |
} |
} |
offset = highwater = 0; |
offset = highwater = 0; |
if (resume_flag) { |
if (resume_flag) { |
if (fstat(local_fd, &st) == -1) { |
if (fstat(local_fd, &st) == -1) { |
error("Unable to stat local file \"%s\": %s", |
error("stat local \"%s\": %s", |
local_path, strerror(errno)); |
local_path, strerror(errno)); |
goto fail; |
goto fail; |
} |
} |
|
|
} |
} |
debug("truncating at %llu", (unsigned long long)highwater); |
debug("truncating at %llu", (unsigned long long)highwater); |
if (ftruncate(local_fd, highwater) == -1) |
if (ftruncate(local_fd, highwater) == -1) |
error("ftruncate \"%s\": %s", local_path, |
error("local ftruncate \"%s\": %s", local_path, |
strerror(errno)); |
strerror(errno)); |
} |
} |
if (read_error) { |
if (read_error) { |
error("Couldn't read from remote file \"%s\" : %s", |
error("read remote \"%s\" : %s", remote_path, fx2txt(status)); |
remote_path, fx2txt(status)); |
|
status = -1; |
status = -1; |
do_close(conn, handle, handle_len); |
do_close(conn, handle, handle_len); |
} else if (write_error) { |
} else if (write_error) { |
error("Couldn't write to \"%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); |
do_close(conn, handle, handle_len); |
|
|
status = SSH2_FX_OK; |
status = SSH2_FX_OK; |
/* Override umask and utimes if asked */ |
/* Override umask and utimes if asked */ |
if (preserve_flag && fchmod(local_fd, mode) == -1) |
if (preserve_flag && fchmod(local_fd, mode) == -1) |
error("Couldn't set mode on \"%s\": %s", local_path, |
error("local chmod \"%s\": %s", local_path, |
strerror(errno)); |
strerror(errno)); |
if (preserve_flag && |
if (preserve_flag && |
(a->flags & SSH2_FILEXFER_ATTR_ACMODTIME)) { |
(a->flags & SSH2_FILEXFER_ATTR_ACMODTIME)) { |
|
|
tv[1].tv_sec = a->mtime; |
tv[1].tv_sec = a->mtime; |
tv[0].tv_usec = tv[1].tv_usec = 0; |
tv[0].tv_usec = tv[1].tv_usec = 0; |
if (utimes(local_path, tv) == -1) |
if (utimes(local_path, tv) == -1) |
error("Can't set times on \"%s\": %s", |
error("local set times \"%s\": %s", |
local_path, strerror(errno)); |
local_path, strerror(errno)); |
} |
} |
if (resume_flag && !lmodified) |
if (resume_flag && !lmodified) |
|
|
else if (fsync_flag) { |
else if (fsync_flag) { |
debug("syncing \"%s\"", local_path); |
debug("syncing \"%s\"", local_path); |
if (fsync(local_fd) == -1) |
if (fsync(local_fd) == -1) |
error("Couldn't sync file \"%s\": %s", |
error("local sync \"%s\": %s", |
local_path, strerror(errno)); |
local_path, strerror(errno)); |
} |
} |
} |
} |
|
|
return -1; |
return -1; |
} |
} |
|
|
|
debug2_f("download dir remote \"%s\" to local \"%s\"", src, dst); |
|
|
if (dirattrib == NULL && |
if (dirattrib == NULL && |
(dirattrib = do_stat(conn, src, 1)) == NULL) { |
(dirattrib = do_stat(conn, src, 1)) == NULL) { |
error("Unable to stat remote directory \"%s\"", src); |
error("stat remote \"%s\" directory failed", src); |
return -1; |
return -1; |
} |
} |
if (!S_ISDIR(dirattrib->perm)) { |
if (!S_ISDIR(dirattrib->perm)) { |
|
|
mode = dirattrib->perm & 01777; |
mode = dirattrib->perm & 01777; |
tmpmode = mode | (S_IWUSR|S_IXUSR); |
tmpmode = mode | (S_IWUSR|S_IXUSR); |
} else { |
} else { |
debug("Server did not send permissions for " |
debug("download remote \"%s\": server " |
"directory \"%s\"", dst); |
"did not send permissions", dst); |
} |
} |
|
|
if (mkdir(dst, tmpmode) == -1 && errno != EEXIST) { |
if (mkdir(dst, tmpmode) == -1 && errno != EEXIST) { |
|
|
} |
} |
|
|
if (do_readdir(conn, src, &dir_entries) == -1) { |
if (do_readdir(conn, src, &dir_entries) == -1) { |
error("%s: Failed to get directory contents", src); |
error("remote readdir \"%s\" failed", src); |
return -1; |
return -1; |
} |
} |
|
|
|
|
ret = -1; |
ret = -1; |
} |
} |
} else |
} else |
logit("%s: not a regular file\n", new_src); |
logit("download \"%s\": not a regular file", new_src); |
|
|
} |
} |
free(new_dst); |
free(new_dst); |
|
|
tv[1].tv_sec = dirattrib->mtime; |
tv[1].tv_sec = dirattrib->mtime; |
tv[0].tv_usec = tv[1].tv_usec = 0; |
tv[0].tv_usec = tv[1].tv_usec = 0; |
if (utimes(dst, tv) == -1) |
if (utimes(dst, tv) == -1) |
error("Can't set times on \"%s\": %s", |
error("local set times on \"%s\": %s", |
dst, strerror(errno)); |
dst, strerror(errno)); |
} else |
} else |
debug("Server did not send times for directory " |
debug("Server did not send times for directory " |
|
|
} |
} |
|
|
if (mode != tmpmode && chmod(dst, mode) == -1) |
if (mode != tmpmode && chmod(dst, mode) == -1) |
error("Can't set final mode on \"%s\": %s", dst, |
error("local chmod directory \"%s\": %s", dst, |
strerror(errno)); |
strerror(errno)); |
|
|
free_sftp_dirents(dir_entries); |
free_sftp_dirents(dir_entries); |
|
|
int ret; |
int ret; |
|
|
if ((src_canon = do_realpath(conn, src)) == NULL) { |
if ((src_canon = do_realpath(conn, src)) == NULL) { |
error("Unable to canonicalize path \"%s\"", src); |
error("download \"%s\": path canonicalization failed", src); |
return -1; |
return -1; |
} |
} |
|
|
|
|
struct requests acks; |
struct requests acks; |
size_t handle_len; |
size_t handle_len; |
|
|
|
debug2_f("upload local \"%s\" to remote \"%s\"", |
|
local_path, remote_path); |
|
|
TAILQ_INIT(&acks); |
TAILQ_INIT(&acks); |
|
|
if ((local_fd = open(local_path, O_RDONLY)) == -1) { |
if ((local_fd = open(local_path, O_RDONLY)) == -1) { |
error("Couldn't open local file \"%s\" for reading: %s", |
error("open local \"%s\": %s", local_path, strerror(errno)); |
local_path, strerror(errno)); |
|
return(-1); |
return(-1); |
} |
} |
if (fstat(local_fd, &sb) == -1) { |
if (fstat(local_fd, &sb) == -1) { |
error("Couldn't fstat local file \"%s\": %s", |
error("fstat local \"%s\": %s", local_path, strerror(errno)); |
local_path, strerror(errno)); |
|
close(local_fd); |
close(local_fd); |
return(-1); |
return(-1); |
} |
} |
if (!S_ISREG(sb.st_mode)) { |
if (!S_ISREG(sb.st_mode)) { |
error("%s is not a regular file", local_path); |
error("local \"%s\" is not a regular file", local_path); |
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("destination file bigger or same size as " |
error("resume \"%s\": destination file " |
"source file"); |
"same size or larger", local_path); |
close(local_fd); |
close(local_fd); |
return -1; |
return -1; |
} |
} |
|
|
len = read(local_fd, data, conn->upload_buflen); |
len = read(local_fd, data, conn->upload_buflen); |
while ((len == -1) && (errno == EINTR || errno == EAGAIN)); |
while ((len == -1) && (errno == EINTR || errno == EAGAIN)); |
|
|
if (len == -1) |
if (len == -1) { |
fatal("Couldn't read from \"%s\": %s", local_path, |
fatal("read local \"%s\": %s", |
strerror(errno)); |
local_path, strerror(errno)); |
|
} else if (len != 0) { |
if (len != 0) { |
|
ack = request_enqueue(&acks, ++id, len, offset); |
ack = request_enqueue(&acks, ++id, len, offset); |
sshbuf_reset(msg); |
sshbuf_reset(msg); |
if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 || |
if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 || |
|
|
free(data); |
free(data); |
|
|
if (status != SSH2_FX_OK) { |
if (status != SSH2_FX_OK) { |
error("Couldn't write to remote file \"%s\": %s", |
error("write remote \"%s\": %s", remote_path, fx2txt(status)); |
remote_path, fx2txt(status)); |
|
status = SSH2_FX_FAILURE; |
status = SSH2_FX_FAILURE; |
} |
} |
|
|
if (close(local_fd) == -1) { |
if (close(local_fd) == -1) { |
error("Couldn't close local file \"%s\": %s", local_path, |
error("close local \"%s\": %s", local_path, strerror(errno)); |
strerror(errno)); |
|
status = SSH2_FX_FAILURE; |
status = SSH2_FX_FAILURE; |
} |
} |
|
|
|
|
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); |
|
|
if (depth >= MAX_DIR_DEPTH) { |
if (depth >= MAX_DIR_DEPTH) { |
error("Maximum directory depth exceeded: %d levels", depth); |
error("Maximum directory depth exceeded: %d levels", depth); |
return -1; |
return -1; |
} |
} |
|
|
if (stat(src, &sb) == -1) { |
if (stat(src, &sb) == -1) { |
error("Couldn't stat directory \"%s\": %s", |
error("stat local \"%s\": %s", src, strerror(errno)); |
src, strerror(errno)); |
|
return -1; |
return -1; |
} |
} |
if (!S_ISDIR(sb.st_mode)) { |
if (!S_ISDIR(sb.st_mode)) { |
|
|
a.perm = saved_perm; |
a.perm = saved_perm; |
|
|
if ((dirp = opendir(src)) == NULL) { |
if ((dirp = opendir(src)) == NULL) { |
error("Failed to open dir \"%s\": %s", src, strerror(errno)); |
error("local opendir \"%s\": %s", src, strerror(errno)); |
return -1; |
return -1; |
} |
} |
|
|
|
|
new_src = path_append(src, filename); |
new_src = path_append(src, filename); |
|
|
if (lstat(new_src, &sb) == -1) { |
if (lstat(new_src, &sb) == -1) { |
logit("%s: lstat failed: %s", filename, |
logit("local lstat \"%s\": %s", filename, |
strerror(errno)); |
strerror(errno)); |
ret = -1; |
ret = -1; |
} else if (S_ISDIR(sb.st_mode)) { |
} else if (S_ISDIR(sb.st_mode)) { |
|
|
(follow_link_flag && S_ISLNK(sb.st_mode))) { |
(follow_link_flag && S_ISLNK(sb.st_mode))) { |
if (do_upload(conn, new_src, new_dst, |
if (do_upload(conn, new_src, new_dst, |
preserve_flag, resume, fsync_flag) == -1) { |
preserve_flag, resume, fsync_flag) == -1) { |
error("Uploading of file %s to %s failed!", |
error("upload \"%s\" to \"%s\" failed", |
new_src, new_dst); |
new_src, new_dst); |
ret = -1; |
ret = -1; |
} |
} |
} else |
} else |
logit("%s: not a regular file\n", filename); |
logit("%s: not a regular file", filename); |
} |
} |
free(new_dst); |
free(new_dst); |
free(new_src); |
free(new_src); |
|
|
int ret; |
int ret; |
|
|
if ((dst_canon = do_realpath(conn, dst)) == NULL) { |
if ((dst_canon = do_realpath(conn, dst)) == NULL) { |
error("Unable to canonicalize path \"%s\"", dst); |
error("upload \"%s\": path canonicalization failed", dst); |
return -1; |
return -1; |
} |
} |
|
|
|
|
struct request *req; |
struct request *req; |
u_char type; |
u_char type; |
|
|
|
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 && (a = do_stat(from, from_path, 0)) == NULL) |
|
|
|
|
if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && |
if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && |
(!S_ISREG(a->perm))) { |
(!S_ISREG(a->perm))) { |
error("Cannot download non-regular file: %s", from_path); |
error("download \"%s\": not a regular file", from_path); |
return(-1); |
return(-1); |
} |
} |
if (a->flags & SSH2_FILEXFER_ATTR_SIZE) |
if (a->flags & SSH2_FILEXFER_ATTR_SIZE) |
|
|
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) { |
error("truncation failed for \"%s\"", to_path); |
error("dest truncate \"%s\" failed", to_path); |
to_handle = NULL; |
to_handle = NULL; |
} |
} |
} |
} |
if (read_error) { |
if (read_error) { |
error("Couldn't read from origin file \"%s\" : %s", |
error("read origin \"%s\": %s", from_path, fx2txt(status)); |
from_path, fx2txt(status)); |
|
status = -1; |
status = -1; |
do_close(from, from_handle, from_handle_len); |
do_close(from, from_handle, from_handle_len); |
if (to_handle != NULL) |
if (to_handle != NULL) |
do_close(to, to_handle, to_handle_len); |
do_close(to, to_handle, to_handle_len); |
} else if (write_error) { |
} else if (write_error) { |
error("Couldn't write to \"%s\": %s", |
error("write dest \"%s\": %s", to_path, fx2txt(write_error)); |
to_path, fx2txt(write_error)); |
|
status = SSH2_FX_FAILURE; |
status = SSH2_FX_FAILURE; |
do_close(from, from_handle, from_handle_len); |
do_close(from, from_handle, from_handle_len); |
if (to_handle != NULL) |
if (to_handle != NULL) |
|
|
mode_t mode = 0777; |
mode_t mode = 0777; |
Attrib curdir; |
Attrib curdir; |
|
|
|
debug2_f("crossload dir src \"%s\" to dst \"%s\"", from_path, to_path); |
|
|
if (depth >= MAX_DIR_DEPTH) { |
if (depth >= MAX_DIR_DEPTH) { |
error("Maximum directory depth exceeded: %d levels", depth); |
error("Maximum directory depth exceeded: %d levels", depth); |
return -1; |
return -1; |
|
|
|
|
if (dirattrib == NULL && |
if (dirattrib == NULL && |
(dirattrib = do_stat(from, from_path, 1)) == NULL) { |
(dirattrib = do_stat(from, from_path, 1)) == NULL) { |
error("Unable to stat remote directory \"%s\"", from_path); |
error("stat remote \"%s\" failed", from_path); |
return -1; |
return -1; |
} |
} |
if (!S_ISDIR(dirattrib->perm)) { |
if (!S_ISDIR(dirattrib->perm)) { |
|
|
curdir.perm = mode; |
curdir.perm = mode; |
|
|
if (do_readdir(from, from_path, &dir_entries) == -1) { |
if (do_readdir(from, from_path, &dir_entries) == -1) { |
error("%s: Failed to get directory contents", from_path); |
error("origin readdir \"%s\" failed", from_path); |
return -1; |
return -1; |
} |
} |
|
|
|
|
if (do_crossload(from, to, new_from_path, new_to_path, |
if (do_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("Transfer of file %s to %s failed", |
error("crossload \"%s\" to \"%s\" failed", |
new_from_path, new_to_path); |
new_from_path, new_to_path); |
ret = -1; |
ret = -1; |
} |
} |
} else |
} else { |
logit("%s: not a regular file\n", new_from_path); |
logit("origin \"%s\": not a regular file", |
|
new_from_path); |
|
} |
} |
} |
free(new_to_path); |
free(new_to_path); |
free(new_from_path); |
free(new_from_path); |
|
|
int ret; |
int ret; |
|
|
if ((from_path_canon = do_realpath(from, from_path)) == NULL) { |
if ((from_path_canon = do_realpath(from, from_path)) == NULL) { |
error("Unable to canonicalize path \"%s\"", from_path); |
error("crossload \"%s\": path canonicalization failed", |
|
from_path); |
return -1; |
return -1; |
} |
} |
|
|