mirror of
https://github.com/upa/mscp.git
synced 2026-02-16 10:54:47 +08:00
fix copy from remote to local and add buffer size
This commit is contained in:
47
src/file.c
47
src/file.c
@@ -324,10 +324,13 @@ static int file_dst_prepare(struct file *f, sftp_session sftp)
|
||||
|
||||
strncpy(path, f->dst_path, sizeof(path));
|
||||
|
||||
pr_debug("prepare for %s\n", path);
|
||||
|
||||
for (p = strchr(path + 1, '/'); p; p = strchr(p + 1, '/')) {
|
||||
*p = '\0';
|
||||
|
||||
ret = file_directory_exists(path, sftp);
|
||||
pr_debug("check %s ret=%d\n", path, ret);
|
||||
if (ret < -1)
|
||||
return -1;
|
||||
if (ret == 1)
|
||||
@@ -479,7 +482,7 @@ int chunk_prepare(struct chunk *c, sftp_session sftp)
|
||||
|
||||
lock_acquire(&f->lock); /* XXX: is always acquiring lock per-chunk heavy? */
|
||||
if (f->state == FILE_STATE_INIT) {
|
||||
if (file_dst_prepare(f, sftp) < 0) {
|
||||
if (file_dst_prepare(f, f->dst_remote ? sftp : NULL) < 0) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
@@ -578,11 +581,11 @@ static int chunk_copy_local_to_remote(struct chunk *c, sftp_session sftp, size_t
|
||||
{
|
||||
struct file *f = c->f;
|
||||
char buf[buf_sz];
|
||||
size_t remaind;
|
||||
size_t remaind, remaind2;
|
||||
sftp_file sf = NULL;
|
||||
mode_t mode;
|
||||
int fd = 0;
|
||||
int ret;
|
||||
int ret, ret2;
|
||||
|
||||
if ((fd = chunk_open_local(f->path, O_RDONLY, c->off)) < 0) {
|
||||
ret = -1;
|
||||
@@ -602,12 +605,15 @@ static int chunk_copy_local_to_remote(struct chunk *c, sftp_session sftp, size_t
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = sftp_write(sf, buf, ret);
|
||||
if (ret < 0) {
|
||||
pr_err("failed to write to %s: %s\n", f->dst_path,
|
||||
ssh_get_error(sftp_ssh(sftp)));
|
||||
ret = -1;
|
||||
goto out;
|
||||
for (remaind2 = ret; remaind2 > 0;) {
|
||||
ret2 = sftp_write(sf, buf + (ret - remaind2), remaind2);
|
||||
if (ret2 < 2) {
|
||||
pr_err("failed to write to %s: %s\n", f->dst_path,
|
||||
ssh_get_error(sftp_ssh(sftp)));
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
remaind2 -= ret;
|
||||
}
|
||||
|
||||
remaind -= ret;
|
||||
@@ -633,11 +639,11 @@ static int chunk_copy_remote_to_local(struct chunk *c, sftp_session sftp, size_t
|
||||
{
|
||||
struct file *f = c->f;
|
||||
char buf[buf_sz];
|
||||
size_t remaind;
|
||||
size_t remaind, remaind2;
|
||||
sftp_file sf = NULL;
|
||||
mode_t mode;
|
||||
int fd = 0;
|
||||
int ret;
|
||||
int ret, ret2;
|
||||
|
||||
if ((fd = chunk_open_local(f->dst_path, O_WRONLY | O_CREAT, c->off)) < 0) {
|
||||
ret = -1;
|
||||
@@ -650,22 +656,25 @@ static int chunk_copy_remote_to_local(struct chunk *c, sftp_session sftp, size_t
|
||||
}
|
||||
|
||||
for (remaind = c->len; remaind > 0;) {
|
||||
ret = sftp_read(sf, buf, ret);
|
||||
ret = sftp_read(sf, buf, buf_sz);
|
||||
if (ret < 0) {
|
||||
pr_err("failed to write to %s: %s\n", f->dst_path,
|
||||
pr_err("failed to read from %s: %s\n", f->dst_path,
|
||||
ssh_get_error(sftp_ssh(sftp)));
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = write(fd, buf, buf_sz);
|
||||
if (ret < 0) {
|
||||
pr_err("failed to read %s: %s\n", f->path, strerrno());
|
||||
ret = -1;
|
||||
goto out;
|
||||
for (remaind2 = ret; remaind2 > 0;) {
|
||||
ret2 = write(fd, buf + (ret - remaind2), remaind2);
|
||||
if (ret2 < 2) {
|
||||
pr_err("failed to write to %s: %s\n", f->dst_path,
|
||||
strerrno());
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
remaind2 -= ret;
|
||||
}
|
||||
|
||||
|
||||
remaind -= ret;
|
||||
}
|
||||
|
||||
|
||||
24
src/main.c
24
src/main.c
@@ -12,7 +12,9 @@
|
||||
|
||||
int verbose = 0; /* util.h */
|
||||
|
||||
#define DEFAULT_MIN_CHUNK_SZ (64 << 20) /* 64MB */
|
||||
#define DEFAULT_MIN_CHUNK_SZ (64 << 20) /* 64MB */
|
||||
#define DEFAULT_BUF_SZ 32768 /* CHANNEL_MAX_PACKET in libssh */
|
||||
/* XXX: passing over CHANNEL_MAX_PACKET bytes to sftp_write stalls */
|
||||
|
||||
struct sscp {
|
||||
char *host; /* remote host (and username) */
|
||||
@@ -22,7 +24,9 @@ struct sscp {
|
||||
struct list_head chunk_list;
|
||||
lock chunk_lock; /* lock for chunk list */
|
||||
|
||||
char *target;
|
||||
char *target;
|
||||
|
||||
int buf_sz;
|
||||
};
|
||||
|
||||
void usage(bool print_help) {
|
||||
@@ -39,6 +43,10 @@ void usage(bool print_help) {
|
||||
printf(" -n NR_CONNECTIONS max number of connections (default: # of cpu cores)\n"
|
||||
" -s MIN_CHUNKSIZE min chunk size (default: 64MB)\n"
|
||||
" -S MAX_CHUNKSIZE max chunk size (default: filesize / nr_conn)\n"
|
||||
" -b BUFFER_SIZE buffer size for read/write (default 32768B)\n"
|
||||
" Note that this value is derived from\n"
|
||||
" CHANNEL_MAX_PACKET in libssh. Recommend NOT\n"
|
||||
" exceeds this value.\n"
|
||||
"\n"
|
||||
" -l LOGIN_NAME login name\n"
|
||||
" -p PORT port number\n"
|
||||
@@ -114,8 +122,9 @@ int main(int argc, char **argv)
|
||||
INIT_LIST_HEAD(&sscp.file_list);
|
||||
INIT_LIST_HEAD(&sscp.chunk_list);
|
||||
lock_init(&sscp.chunk_lock);
|
||||
sscp.buf_sz = DEFAULT_BUF_SZ;
|
||||
|
||||
while ((ch = getopt(argc, argv, "n:s:S:l:p:i:c:Cvh")) != -1) {
|
||||
while ((ch = getopt(argc, argv, "n:s:S:b:l:p:i:c:Cvh")) != -1) {
|
||||
switch (ch) {
|
||||
case 'n':
|
||||
nr_conn = atoi(optarg);
|
||||
@@ -154,6 +163,13 @@ int main(int argc, char **argv)
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
sscp.buf_sz = atoi(optarg);
|
||||
if (sscp.buf_sz < 1) {
|
||||
pr_err("invalid buffer size: %s\n", optarg);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
opts.login_name = optarg;
|
||||
break;
|
||||
@@ -245,7 +261,7 @@ int main(int argc, char **argv)
|
||||
struct chunk *c;
|
||||
list_for_each_entry(c, &sscp.chunk_list, list) {
|
||||
chunk_prepare(c, sscp.ctrl);
|
||||
chunk_copy(c, sscp.ctrl, 8192);
|
||||
chunk_copy(c, sscp.ctrl, sscp.buf_sz);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user