version 1.106, 2013/10/11 02:52:23 |
version 1.107, 2013/10/17 00:30:13 |
|
|
#define SFTP_EXT_STATVFS 0x00000002 |
#define SFTP_EXT_STATVFS 0x00000002 |
#define SFTP_EXT_FSTATVFS 0x00000004 |
#define SFTP_EXT_FSTATVFS 0x00000004 |
#define SFTP_EXT_HARDLINK 0x00000008 |
#define SFTP_EXT_HARDLINK 0x00000008 |
|
#define SFTP_EXT_FSYNC 0x00000010 |
u_int exts; |
u_int exts; |
u_int64_t limit_kbps; |
u_int64_t limit_kbps; |
struct bwlimit bwlimit_in, bwlimit_out; |
struct bwlimit bwlimit_in, bwlimit_out; |
|
|
strcmp(value, "1") == 0) { |
strcmp(value, "1") == 0) { |
ret->exts |= SFTP_EXT_HARDLINK; |
ret->exts |= SFTP_EXT_HARDLINK; |
known = 1; |
known = 1; |
|
} else if (strcmp(name, "fsync@openssh.com") == 0 && |
|
strcmp(value, "1") == 0) { |
|
ret->exts |= SFTP_EXT_FSYNC; |
|
known = 1; |
} |
} |
if (known) { |
if (known) { |
debug2("Server supports extension \"%s\" revision %s", |
debug2("Server supports extension \"%s\" revision %s", |
|
|
if (type == SSH2_FXP_STATUS) { |
if (type == SSH2_FXP_STATUS) { |
u_int status = buffer_get_int(&msg); |
u_int status = buffer_get_int(&msg); |
|
|
error("Couldn't canonicalise: %s", fx2txt(status)); |
error("Couldn't canonicalize: %s", fx2txt(status)); |
buffer_free(&msg); |
buffer_free(&msg); |
return NULL; |
return NULL; |
} else if (type != SSH2_FXP_NAME) |
} else if (type != SSH2_FXP_NAME) |
|
|
return(status); |
return(status); |
} |
} |
|
|
|
int |
|
do_fsync(struct sftp_conn *conn, char *handle, u_int handle_len) |
|
{ |
|
Buffer msg; |
|
u_int status, id; |
|
|
|
/* Silently return if the extension is not supported */ |
|
if ((conn->exts & SFTP_EXT_FSYNC) == 0) |
|
return -1; |
|
|
|
buffer_init(&msg); |
|
|
|
/* Send fsync request */ |
|
id = conn->msg_id++; |
|
|
|
buffer_put_char(&msg, SSH2_FXP_EXTENDED); |
|
buffer_put_int(&msg, id); |
|
buffer_put_cstring(&msg, "fsync@openssh.com"); |
|
buffer_put_string(&msg, handle, handle_len); |
|
send_msg(conn, &msg); |
|
debug3("Sent message fsync@openssh.com I:%u", id); |
|
buffer_free(&msg); |
|
|
|
status = get_status(conn, id); |
|
if (status != SSH2_FX_OK) |
|
error("Couldn't sync file: %s", fx2txt(status)); |
|
|
|
return status; |
|
} |
|
|
#ifdef notyet |
#ifdef notyet |
char * |
char * |
do_readlink(struct sftp_conn *conn, char *path) |
do_readlink(struct sftp_conn *conn, char *path) |
|
|
|
|
int |
int |
do_download(struct sftp_conn *conn, char *remote_path, char *local_path, |
do_download(struct sftp_conn *conn, char *remote_path, char *local_path, |
Attrib *a, int preserve_flag, int resume_flag) |
Attrib *a, int preserve_flag, int resume_flag, int fsync_flag) |
{ |
{ |
Attrib junk; |
Attrib junk; |
Buffer msg; |
Buffer msg; |
|
|
error("Can't set times on \"%s\": %s", |
error("Can't set times on \"%s\": %s", |
local_path, strerror(errno)); |
local_path, strerror(errno)); |
} |
} |
|
if (fsync_flag) { |
|
debug("syncing \"%s\"", local_path); |
|
if (fsync(local_fd) == -1) |
|
error("Couldn't sync file \"%s\": %s", |
|
local_path, strerror(errno)); |
|
} |
} |
} |
close(local_fd); |
close(local_fd); |
buffer_free(&msg); |
buffer_free(&msg); |
|
|
|
|
static int |
static int |
download_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth, |
download_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth, |
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 i, ret = 0; |
int i, ret = 0; |
SFTP_DIRENT **dir_entries; |
SFTP_DIRENT **dir_entries; |
|
|
continue; |
continue; |
if (download_dir_internal(conn, new_src, new_dst, |
if (download_dir_internal(conn, new_src, new_dst, |
depth + 1, &(dir_entries[i]->a), preserve_flag, |
depth + 1, &(dir_entries[i]->a), preserve_flag, |
print_flag, resume_flag) == -1) |
print_flag, resume_flag, fsync_flag) == -1) |
ret = -1; |
ret = -1; |
} else if (S_ISREG(dir_entries[i]->a.perm) ) { |
} else if (S_ISREG(dir_entries[i]->a.perm) ) { |
if (do_download(conn, new_src, new_dst, |
if (do_download(conn, new_src, new_dst, |
&(dir_entries[i]->a), preserve_flag, resume_flag) == -1) { |
&(dir_entries[i]->a), preserve_flag, |
|
resume_flag, fsync_flag) == -1) { |
error("Download of file %s to %s failed", |
error("Download of file %s to %s failed", |
new_src, new_dst); |
new_src, new_dst); |
ret = -1; |
ret = -1; |
|
|
|
|
int |
int |
download_dir(struct sftp_conn *conn, char *src, char *dst, |
download_dir(struct sftp_conn *conn, char *src, 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) |
{ |
{ |
char *src_canon; |
char *src_canon; |
int ret; |
int ret; |
|
|
if ((src_canon = do_realpath(conn, src)) == NULL) { |
if ((src_canon = do_realpath(conn, src)) == NULL) { |
error("Unable to canonicalise path \"%s\"", src); |
error("Unable to canonicalize path \"%s\"", src); |
return -1; |
return -1; |
} |
} |
|
|
ret = download_dir_internal(conn, src_canon, dst, 0, |
ret = download_dir_internal(conn, src_canon, dst, 0, |
dirattrib, preserve_flag, print_flag, resume_flag); |
dirattrib, preserve_flag, print_flag, resume_flag, fsync_flag); |
free(src_canon); |
free(src_canon); |
return ret; |
return ret; |
} |
} |
|
|
int |
int |
do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, |
do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, |
int preserve_flag) |
int preserve_flag, int fsync_flag) |
{ |
{ |
int local_fd; |
int local_fd; |
int status = SSH2_FX_OK; |
int status = SSH2_FX_OK; |
|
|
if (preserve_flag) |
if (preserve_flag) |
do_fsetstat(conn, handle, handle_len, &a); |
do_fsetstat(conn, handle, handle_len, &a); |
|
|
|
if (fsync_flag) |
|
(void)do_fsync(conn, handle, handle_len); |
|
|
if (do_close(conn, handle, handle_len) != SSH2_FX_OK) |
if (do_close(conn, handle, handle_len) != SSH2_FX_OK) |
status = -1; |
status = -1; |
free(handle); |
free(handle); |
|
|
|
|
static int |
static int |
upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth, |
upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth, |
int preserve_flag, int print_flag) |
int preserve_flag, int print_flag, int fsync_flag) |
{ |
{ |
int ret = 0, status; |
int ret = 0, status; |
DIR *dirp; |
DIR *dirp; |
|
|
continue; |
continue; |
|
|
if (upload_dir_internal(conn, new_src, new_dst, |
if (upload_dir_internal(conn, new_src, new_dst, |
depth + 1, preserve_flag, print_flag) == -1) |
depth + 1, preserve_flag, print_flag, |
|
fsync_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 (do_upload(conn, new_src, new_dst, |
preserve_flag) == -1) { |
preserve_flag, fsync_flag) == -1) { |
error("Uploading of file %s to %s failed!", |
error("Uploading of file %s to %s failed!", |
new_src, new_dst); |
new_src, new_dst); |
ret = -1; |
ret = -1; |
|
|
|
|
int |
int |
upload_dir(struct sftp_conn *conn, char *src, char *dst, int preserve_flag, |
upload_dir(struct sftp_conn *conn, char *src, char *dst, int preserve_flag, |
int print_flag) |
int print_flag, int fsync_flag) |
{ |
{ |
char *dst_canon; |
char *dst_canon; |
int ret; |
int ret; |
|
|
if ((dst_canon = do_realpath(conn, dst)) == NULL) { |
if ((dst_canon = do_realpath(conn, dst)) == NULL) { |
error("Unable to canonicalise path \"%s\"", dst); |
error("Unable to canonicalize path \"%s\"", dst); |
return -1; |
return -1; |
} |
} |
|
|
ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag, |
ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag, |
print_flag); |
print_flag, fsync_flag); |
|
|
free(dst_canon); |
free(dst_canon); |
return ret; |
return ret; |
} |
} |