summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRyo Nakamura <upa@haeena.net>2022-10-29 23:48:50 +0900
committerRyo Nakamura <upa@haeena.net>2022-10-29 23:48:50 +0900
commitc76fa3141dd648b145dde2534a1ca3824ff81466 (patch)
tree6be1bc1f5ce8c0a200b65cba34987b1df2844239 /src
parentff697aa514b13cbb8105f2f3c04c1889820796d9 (diff)
change indent from space to tab
Diffstat (limited to 'src')
-rw-r--r--src/atomic.h50
-rw-r--r--src/file.c1220
-rw-r--r--src/file.h34
-rw-r--r--src/main.c832
-rw-r--r--src/platform.c22
-rw-r--r--src/pprint.c20
-rw-r--r--src/ssh.c440
-rw-r--r--src/ssh.h16
-rw-r--r--src/util.h6
9 files changed, 1320 insertions, 1320 deletions
diff --git a/src/atomic.h b/src/atomic.h
index 4f643e9..e0e735d 100644
--- a/src/atomic.h
+++ b/src/atomic.h
@@ -9,12 +9,12 @@ typedef int refcnt;
static inline void refcnt_inc(refcnt *cnt)
{
- __sync_add_and_fetch(cnt, 1);
+ __sync_add_and_fetch(cnt, 1);
}
static inline refcnt refcnt_dec(refcnt *cnt)
{
- return __sync_sub_and_fetch(cnt, 1);
+ return __sync_sub_and_fetch(cnt, 1);
}
@@ -22,37 +22,37 @@ typedef pthread_mutex_t lock;
static inline void lock_init(lock *l)
{
- pthread_mutex_init(l, NULL);
+ pthread_mutex_init(l, NULL);
}
static inline void lock_acquire(lock *l)
{
- int ret = pthread_mutex_lock(l);
- if (ret < 0) {
- switch (ret) {
- case EINVAL:
- pr_err("invalid mutex\n");
- exit(1);
- case EDEADLK:
- pr_err("a deadlock would occur\n");
- exit(1);
- }
- }
+ int ret = pthread_mutex_lock(l);
+ if (ret < 0) {
+ switch (ret) {
+ case EINVAL:
+ pr_err("invalid mutex\n");
+ exit(1);
+ case EDEADLK:
+ pr_err("a deadlock would occur\n");
+ exit(1);
+ }
+ }
}
static inline void lock_release(lock *l)
{
- int ret = pthread_mutex_unlock(l);
- if (ret < 0) {
- switch (ret) {
- case EINVAL:
- pr_err("invalid mutex\n");
- exit(1);
- case EPERM:
- pr_err("this thread does not hold this mutex\n");
- exit(1);
- }
- }
+ int ret = pthread_mutex_unlock(l);
+ if (ret < 0) {
+ switch (ret) {
+ case EINVAL:
+ pr_err("invalid mutex\n");
+ exit(1);
+ case EPERM:
+ pr_err("this thread does not hold this mutex\n");
+ exit(1);
+ }
+ }
}
#endif /* _ATOMIC_H_ */
diff --git a/src/file.c b/src/file.c
index 89babd0..3e1f675 100644
--- a/src/file.c
+++ b/src/file.c
@@ -13,758 +13,758 @@
bool file_has_hostname(char *path)
{
- char *p;
+ char *p;
- p = strchr(path, ':');
- if (p) {
- if (p == path || ((p > path) && *(p - 1) == '\\'))
- return false; /* first byte is colon or escaped colon, skip */
- else
- return true;
- }
+ p = strchr(path, ':');
+ if (p) {
+ if (p == path || ((p > path) && *(p - 1) == '\\'))
+ return false; /* first byte is colon or escaped colon, skip */
+ else
+ return true;
+ }
- return false;
+ return false;
}
char *file_find_hostname(char *path)
{
- char *dup, *p;
-
- dup = strdup(path);
- if (!dup) {
- pr_err("%s", strerrno());
- return NULL;
- }
-
- p = strchr(dup, ':');
- if (p) {
- if (p == dup || ((p > dup) && *(p - 1) == '\\')) {
- /* first byte is colon or escaped colon, skip */
- free(dup);
- } else {
- /* handle this as remote hostname (with username) */
- *p = '\0';
- return dup;
- }
- }
-
- return NULL;
+ char *dup, *p;
+
+ dup = strdup(path);
+ if (!dup) {
+ pr_err("%s", strerrno());
+ return NULL;
+ }
+
+ p = strchr(dup, ':');
+ if (p) {
+ if (p == dup || ((p > dup) && *(p - 1) == '\\')) {
+ /* first byte is colon or escaped colon, skip */
+ free(dup);
+ } else {
+ /* handle this as remote hostname (with username) */
+ *p = '\0';
+ return dup;
+ }
+ }
+
+ return NULL;
}
static char *file_find_path(char *path)
{
- char *p;
-
- p = strchr(path, ':');
- if (p) {
- if (p == path || ((p > path) && *(p - 1) == '\\')) {
- /* first byte is colon or escaped colon, skip */
- return path;
- } else {
- return p + 1;
- }
- }
-
- return path;
+ char *p;
+
+ p = strchr(path, ':');
+ if (p) {
+ if (p == path || ((p > path) && *(p - 1) == '\\')) {
+ /* first byte is colon or escaped colon, skip */
+ return path;
+ } else {
+ return p + 1;
+ }
+ }
+
+ return path;
}
/* return 1 when path is directory, 0 is not directory, and -1 on error */
static int file_is_directory(char *path, sftp_session sftp, bool print_error)
{
- int ret = 0;
-
- if (sftp) {
- char *remote_path = file_find_path(path);
- sftp_attributes attr;
-
- char *p = *remote_path == '\0' ? "." : remote_path;
- attr = sftp_stat(sftp, p);
- if (!attr) {
- if (print_error)
- pr_err("sftp_stat %s: %s\n",
- path, sftp_get_ssh_error(sftp));
- ret = -1;
- } else if (attr->type == SSH_FILEXFER_TYPE_DIRECTORY)
- ret = 1;
- sftp_attributes_free(attr);
- } else {
- struct stat statbuf;
- if (stat(path, &statbuf) < 0) {
- if (print_error)
- pr_err("stat %s: %s\n", path, strerrno());
- ret = -1;
- } else if (S_ISDIR(statbuf.st_mode))
- ret = 1;
- }
-
- return ret;
+ int ret = 0;
+
+ if (sftp) {
+ char *remote_path = file_find_path(path);
+ sftp_attributes attr;
+
+ char *p = *remote_path == '\0' ? "." : remote_path;
+ attr = sftp_stat(sftp, p);
+ if (!attr) {
+ if (print_error)
+ pr_err("sftp_stat %s: %s\n",
+ path, sftp_get_ssh_error(sftp));
+ ret = -1;
+ } else if (attr->type == SSH_FILEXFER_TYPE_DIRECTORY)
+ ret = 1;
+ sftp_attributes_free(attr);
+ } else {
+ struct stat statbuf;
+ if (stat(path, &statbuf) < 0) {
+ if (print_error)
+ pr_err("stat %s: %s\n", path, strerrno());
+ ret = -1;
+ } else if (S_ISDIR(statbuf.st_mode))
+ ret = 1;
+ }
+
+ return ret;
}
/* return 1 when directory exists, 0 not exists, and -1 on error */
int file_directory_exists(char *path, sftp_session sftp)
{
- int ret = 0;
-
- if (sftp) {
- sftp_attributes attr;
- attr = sftp_stat(sftp, path);
- if (!attr) {
- if (sftp_get_error(sftp) == SSH_FX_NO_SUCH_PATH ||
- sftp_get_error(sftp) == SSH_FX_NO_SUCH_FILE)
- ret = 0;
- else {
- pr_err("%s: %s\n", path, ssh_get_error(sftp_ssh(sftp)));
- ret = -1;
- }
- } else if (attr->type == SSH_FILEXFER_TYPE_DIRECTORY)
- ret = 1;
- sftp_attributes_free(attr);
- } else {
- struct stat statbuf;
- if (stat(path, &statbuf) < 0) {
- if (errno == ENOENT)
- ret = 0;
- else {
- pr_err("%s: %s\n", path, strerrno());
- ret = -1;
- }
- } else if ((statbuf.st_mode & S_IFMT) == S_IFDIR)
- ret = 1;
- }
-
- return ret;
+ int ret = 0;
+
+ if (sftp) {
+ sftp_attributes attr;
+ attr = sftp_stat(sftp, path);
+ if (!attr) {
+ if (sftp_get_error(sftp) == SSH_FX_NO_SUCH_PATH ||
+ sftp_get_error(sftp) == SSH_FX_NO_SUCH_FILE)
+ ret = 0;
+ else {
+ pr_err("%s: %s\n", path, ssh_get_error(sftp_ssh(sftp)));
+ ret = -1;
+ }
+ } else if (attr->type == SSH_FILEXFER_TYPE_DIRECTORY)
+ ret = 1;
+ sftp_attributes_free(attr);
+ } else {
+ struct stat statbuf;
+ if (stat(path, &statbuf) < 0) {
+ if (errno == ENOENT)
+ ret = 0;
+ else {
+ pr_err("%s: %s\n", path, strerrno());
+ ret = -1;
+ }
+ } else if ((statbuf.st_mode & S_IFMT) == S_IFDIR)
+ ret = 1;
+ }
+
+ return ret;
}
static struct file *file_alloc(char *path, size_t size, bool remote)
{
- struct file *f;
-
- f = malloc(sizeof(*f));
- if (!f) {
- pr_err("%s\n", strerrno());
- return NULL;
- }
- memset(f, 0, sizeof(*f));
-
- strncpy(f->path, path, PATH_MAX - 1);
- f->size = size;
- f->remote = remote;
- f->dst_remote = !remote;
- lock_init(&f->lock);
-
- return f;
+ struct file *f;
+
+ f = malloc(sizeof(*f));
+ if (!f) {
+ pr_err("%s\n", strerrno());
+ return NULL;
+ }
+ memset(f, 0, sizeof(*f));
+
+ strncpy(f->path, path, PATH_MAX - 1);
+ f->size = size;
+ f->remote = remote;
+ f->dst_remote = !remote;
+ lock_init(&f->lock);
+
+ return f;
}
static bool file_should_skip(char *path)
{
- int len = strlen(path);
- if ((len == 1 && strncmp(path, ".", 1) == 0) ||
- (len == 2 && strncmp(path, "..", 2) == 0)) {
- return true;
- }
- return false;
+ int len = strlen(path);
+ if ((len == 1 && strncmp(path, ".", 1) == 0) ||
+ (len == 2 && strncmp(path, "..", 2) == 0)) {
+ return true;
+ }
+ return false;
}
/* return -1 when error, 0 when should skip, and 1 when should be copied */
static int check_file_tobe_copied(char *path, sftp_session sftp, size_t *size)
{
- struct stat statbuf;
- sftp_attributes attr;
- int ret = 0;
-
- if (!sftp) {
- /* local */
- if (stat(path, &statbuf) < 0) {
- pr_err("failed to get stat for %s: %s\n", path, strerrno());
- return -1;
- }
- if (S_ISREG(statbuf.st_mode)) {
- *size = statbuf.st_size;
- return 1;
- }
- return 0;
- }
-
- /* remote */
- attr = sftp_stat(sftp, path);
- if (!attr) {
- pr_err("failed to get stat for %s: %s\n",
- path, ssh_get_error(sftp_ssh(sftp)));
- return -1;
- }
- if (attr->type == SSH_FILEXFER_TYPE_REGULAR ||
- attr->type == SSH_FILEXFER_TYPE_SYMLINK) {
- *size = attr->size;
- ret = 1;
- }
-
- sftp_attributes_free(attr);
-
- return ret;
+ struct stat statbuf;
+ sftp_attributes attr;
+ int ret = 0;
+
+ if (!sftp) {
+ /* local */
+ if (stat(path, &statbuf) < 0) {
+ pr_err("failed to get stat for %s: %s\n", path, strerrno());
+ return -1;
+ }
+ if (S_ISREG(statbuf.st_mode)) {
+ *size = statbuf.st_size;
+ return 1;
+ }
+ return 0;
+ }
+
+ /* remote */
+ attr = sftp_stat(sftp, path);
+ if (!attr) {
+ pr_err("failed to get stat for %s: %s\n",
+ path, ssh_get_error(sftp_ssh(sftp)));
+ return -1;
+ }
+ if (attr->type == SSH_FILEXFER_TYPE_REGULAR ||
+ attr->type == SSH_FILEXFER_TYPE_SYMLINK) {
+ *size = attr->size;
+ ret = 1;
+ }
+
+ sftp_attributes_free(attr);
+
+ return ret;
}
static int file_fill_recursive(struct list_head *file_list,
- bool dst_is_remote, sftp_session sftp, char *src_path,
- char *rel_path, char *dst_path, bool dst_should_dir)
+ bool dst_is_remote, sftp_session sftp, char *src_path,
+ char *rel_path, char *dst_path, bool dst_should_dir)
{
- char next_src_path[PATH_MAX], next_rel_path[PATH_MAX];
- struct file *f;
- size_t size;
- int ret;
-
- ret = file_is_directory(src_path, dst_is_remote ? NULL : sftp, true);
- if (ret < 0)
- return -1;
-
- if (ret == 0) {
- /* src_path is file */
- ret = check_file_tobe_copied(src_path, dst_is_remote ? NULL : sftp,
- &size);
- if (ret <= 0)
- return ret; /* error or skip */
-
- if ((f = file_alloc(src_path, size, !dst_is_remote)) == NULL) {
- pr_err("%s\n", strerrno());
- return -1;
- }
-
- if (dst_should_dir)
- snprintf(f->dst_path, PATH_MAX, "%s/%s%s",
- dst_path, rel_path, basename(src_path));
- else
- snprintf(f->dst_path, PATH_MAX, "%s%s", rel_path, dst_path);
-
- list_add_tail(&f->list, file_list);
- pprint2("file %s %s -> %s %s\n",
- f->path, dst_is_remote ? "(local)" : "(remote)",
- f->dst_path, dst_is_remote ? "(remote)" : "(local)");
-
- return 0;
- }
-
- /* src_path is directory */
- if (dst_is_remote) {
- /* src_path is local directory */
- struct dirent *de;
- DIR *dir;
- if ((dir = opendir(src_path)) == NULL) {
- pr_err("opendir '%s': %s\n", src_path, strerrno());
- return -1;
- }
- while ((de = readdir(dir)) != NULL) {
- if (file_should_skip(de->d_name))
- continue;
- snprintf(next_src_path, sizeof(next_src_path),
- "%s/%s", src_path, de->d_name);
- snprintf(next_rel_path, sizeof(next_rel_path),
- "%s%s/", rel_path, basename(src_path));
- ret = file_fill_recursive(file_list, dst_is_remote, sftp,
- next_src_path, next_rel_path,
- dst_path, dst_should_dir);
- if (ret < 0)
- return ret;
- }
- } else {
- /* src_path is remote directory */
- sftp_attributes attr;
- sftp_dir dir;
- if ((dir = sftp_opendir(sftp, src_path)) == NULL) {
- pr_err("sftp_opendir: '%s': %s\n", src_path,
- sftp_get_ssh_error(sftp));
- return -1;
- }
- while ((attr = sftp_readdir(sftp, dir)) != NULL) {
- if (file_should_skip(attr->name))
- continue;
- snprintf(next_src_path, sizeof(next_src_path),
- "%s/%s", src_path, attr->name);
- snprintf(next_rel_path, sizeof(next_rel_path),
- "%s%s/", rel_path, basename(src_path));
- ret = file_fill_recursive(file_list, dst_is_remote, sftp,
- next_src_path, next_rel_path,
- dst_path, dst_should_dir);
- if (ret < 0)
- return ret;
- }
- }
-
- return 0;
+ char next_src_path[PATH_MAX], next_rel_path[PATH_MAX];
+ struct file *f;
+ size_t size;
+ int ret;
+
+ ret = file_is_directory(src_path, dst_is_remote ? NULL : sftp, true);
+ if (ret < 0)
+ return -1;
+
+ if (ret == 0) {
+ /* src_path is file */
+ ret = check_file_tobe_copied(src_path, dst_is_remote ? NULL : sftp,
+ &size);
+ if (ret <= 0)
+ return ret; /* error or skip */
+
+ if ((f = file_alloc(src_path, size, !dst_is_remote)) == NULL) {
+ pr_err("%s\n", strerrno());
+ return -1;
+ }
+
+ if (dst_should_dir)
+ snprintf(f->dst_path, PATH_MAX, "%s/%s%s",
+ dst_path, rel_path, basename(src_path));
+ else
+ snprintf(f->dst_path, PATH_MAX, "%s%s", rel_path, dst_path);
+
+ list_add_tail(&f->list, file_list);
+ pprint2("file %s %s -> %s %s\n",
+ f->path, dst_is_remote ? "(local)" : "(remote)",
+ f->dst_path, dst_is_remote ? "(remote)" : "(local)");
+
+ return 0;
+ }
+
+ /* src_path is directory */
+ if (dst_is_remote) {
+ /* src_path is local directory */
+ struct dirent *de;
+ DIR *dir;
+ if ((dir = opendir(src_path)) == NULL) {
+ pr_err("opendir '%s': %s\n", src_path, strerrno());
+ return -1;
+ }
+ while ((de = readdir(dir)) != NULL) {
+ if (file_should_skip(de->d_name))
+ continue;
+ snprintf(next_src_path, sizeof(next_src_path),
+ "%s/%s", src_path, de->d_name);
+ snprintf(next_rel_path, sizeof(next_rel_path),
+ "%s%s/", rel_path, basename(src_path));
+ ret = file_fill_recursive(file_list, dst_is_remote, sftp,
+ next_src_path, next_rel_path,
+ dst_path, dst_should_dir);
+ if (ret < 0)
+ return ret;
+ }
+ } else {
+ /* src_path is remote directory */
+ sftp_attributes attr;
+ sftp_dir dir;
+ if ((dir = sftp_opendir(sftp, src_path)) == NULL) {
+ pr_err("sftp_opendir: '%s': %s\n", src_path,
+ sftp_get_ssh_error(sftp));
+ return -1;
+ }
+ while ((attr = sftp_readdir(sftp, dir)) != NULL) {
+ if (file_should_skip(attr->name))
+ continue;
+ snprintf(next_src_path, sizeof(next_src_path),
+ "%s/%s", src_path, attr->name);
+ snprintf(next_rel_path, sizeof(next_rel_path),
+ "%s%s/", rel_path, basename(src_path));
+ ret = file_fill_recursive(file_list, dst_is_remote, sftp,
+ next_src_path, next_rel_path,
+ dst_path, dst_should_dir);
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ return 0;
}
int file_fill(sftp_session sftp, struct list_head *file_list, char **src_array, int cnt,
- char *dst)
+ char *dst)
{
- bool dst_is_remote, dst_is_dir, dst_should_dir;
- char *dst_path, *src_path;
- int n, ret;
-
- dst_path = file_find_path(dst);
- dst_path = *dst_path == '\0' ? "." : dst_path;
- dst_is_remote = file_find_hostname(dst) ? true : false;
-
- if (file_is_directory(dst_path, dst_is_remote ? sftp : NULL, false) > 0)
- dst_is_dir = true;
- else
- dst_is_dir = false;
-
- for (n = 0; n < cnt; n++) {
- src_path = file_find_path(src_array[n]);
-
- if (file_is_directory(src_path, dst_is_remote ? NULL : sftp, false) > 0)
- dst_should_dir = true;
- else
- dst_should_dir = false;
- ret = file_fill_recursive(file_list, dst_is_remote, sftp,
- src_path, "",
- dst_path, dst_is_dir | dst_should_dir);
- if (ret < 0)
- return ret;
- }
-
- return 0;
+ bool dst_is_remote, dst_is_dir, dst_should_dir;
+ char *dst_path, *src_path;
+ int n, ret;
+
+ dst_path = file_find_path(dst);
+ dst_path = *dst_path == '\0' ? "." : dst_path;
+ dst_is_remote = file_find_hostname(dst) ? true : false;
+
+ if (file_is_directory(dst_path, dst_is_remote ? sftp : NULL, false) > 0)
+ dst_is_dir = true;
+ else
+ dst_is_dir = false;
+
+ for (n = 0; n < cnt; n++) {
+ src_path = file_find_path(src_array[n]);
+
+ if (file_is_directory(src_path, dst_is_remote ? NULL : sftp, false) > 0)
+ dst_should_dir = true;
+ else
+ dst_should_dir = false;
+ ret = file_fill_recursive(file_list, dst_is_remote, sftp,
+ src_path, "",
+ dst_path, dst_is_dir | dst_should_dir);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
}
/* based on
* https://stackoverflow.com/questions/2336242/recursive-mkdir-system-call-on-unix */
static int file_dst_prepare(struct file *f, sftp_session sftp)
{
- /* XXX: should reflect the permission of the original directory? */
- mode_t mode = S_IRWXU | S_IRWXG | S_IRWXO;
- char path[PATH_MAX];
- char *p;
- int ret;
-
- 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)
- goto next;
-
- pr_debug("mkdir %s\n", path);
-
- if (sftp) {
- ret = sftp_mkdir(sftp, path, mode);
- if (ret < 0 &&
- sftp_get_error(sftp) != SSH_FX_FILE_ALREADY_EXISTS) {
- pr_err("failed to create %s: %s\n",
- path, ssh_get_error(sftp_ssh(sftp)));
- return -1;
- }
- } else {
- if (mkdir(path, mode) == -1 && errno != EEXIST) {
- pr_err("failed to create %s: %s\n",
- path, strerrno());
- return -1;
- }
- }
- next:
- *p = '/';
- }
-
- return 0;
+ /* XXX: should reflect the permission of the original directory? */
+ mode_t mode = S_IRWXU | S_IRWXG | S_IRWXO;
+ char path[PATH_MAX];
+ char *p;
+ int ret;
+
+ 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)
+ goto next;
+
+ pr_debug("mkdir %s\n", path);
+
+ if (sftp) {
+ ret = sftp_mkdir(sftp, path, mode);
+ if (ret < 0 &&
+ sftp_get_error(sftp) != SSH_FX_FILE_ALREADY_EXISTS) {
+ pr_err("failed to create %s: %s\n",
+ path, ssh_get_error(sftp_ssh(sftp)));
+ return -1;
+ }
+ } else {
+ if (mkdir(path, mode) == -1 && errno != EEXIST) {
+ pr_err("failed to create %s: %s\n",
+ path, strerrno());
+ return -1;
+ }
+ }
+ next:
+ *p = '/';
+ }
+
+ return 0;
}
#ifdef DEBUG
void file_dump(struct list_head *file_list)
{
- struct file *f;
-
- list_for_each_entry(f, file_list, list) {
- pr_debug("%s %s -> %s %s %lu-byte\n",
- f->path, f->remote ? "(remote)" : "(local)",
- f->dst_path, f->dst_remote ? "(remote)" : "(local)",
- f->size);
- }
+ struct file *f;
+
+ list_for_each_entry(f, file_list, list) {
+ pr_debug("%s %s -> %s %s %lu-byte\n",
+ f->path, f->remote ? "(remote)" : "(local)",
+ f->dst_path, f->dst_remote ? "(remote)" : "(local)",
+ f->size);
+ }
}
#endif
static void *chunk_alloc(struct file *f)
{
- struct chunk *c;
-
- c = malloc(sizeof(*c));
- if (!c) {
- pr_err("%s\n", strerrno());
- return NULL;
- }
- memset(c, 0, sizeof(*c));
-
- c->f = f;
- c->off = 0;
- c->len = 0;
- refcnt_inc(&f->refcnt);
- return c;
+ struct chunk *c;
+
+ c = malloc(sizeof(*c));
+ if (!c) {
+ pr_err("%s\n", strerrno());
+ return NULL;
+ }
+ memset(c, 0, sizeof(*c));
+
+ c->f = f;
+ c->off = 0;
+ c->len = 0;
+ refcnt_inc(&f->refcnt);
+ return c;
}
static int get_page_mask(void)
{
- int n;
- long page_sz = sysconf(_SC_PAGESIZE);
- size_t page_mask = 0;
+ int n;
+ long page_sz = sysconf(_SC_PAGESIZE);
+ size_t page_mask = 0;
- for (n = 0; page_sz > 0; page_sz >>= 1, n++) {
- page_mask <<= 1;
- page_mask |= 1;
- }
+ for (n = 0; page_sz > 0; page_sz >>= 1, n++) {
+ page_mask <<= 1;
+ page_mask |= 1;
+ }
- return page_mask >> 1;
+ return page_mask >> 1;
}
int chunk_fill(struct list_head *file_list, struct list_head *chunk_list,
- int nr_conn, int min_chunk_sz, int max_chunk_sz)
+ int nr_conn, int min_chunk_sz, int max_chunk_sz)
{
- struct chunk *c;
- struct file *f;
- size_t page_mask;
- size_t chunk_sz;
- size_t size;
-
- page_mask = get_page_mask();
-
- list_for_each_entry(f, file_list, list) {
- if (f->size <= min_chunk_sz)
- chunk_sz = f->size;
- else if (max_chunk_sz)
- chunk_sz = max_chunk_sz;
- else {
- chunk_sz = (f->size - (f->size % nr_conn)) / nr_conn;
- chunk_sz &= ~page_mask; /* align in page_sz */
- if (chunk_sz <= min_chunk_sz)
- chunk_sz = min_chunk_sz;
- }
-
- pr_debug("%s chunk_sz %lu-byte\n", f->path, chunk_sz);
-
- for (size = f->size; size > 0;) {
- c = chunk_alloc(f);
- if (!c)
- return -1;
- c->off = f->size - size;
- c->len = size < chunk_sz ? size : chunk_sz;
- size -= c->len;
- list_add_tail(&c->list, chunk_list);
- pprint4("chunk %s 0x%010lx-0x%010lx %luB\n",
- c->f->path, c->off, c->off + c->len, c->len);
- }
- }
-
- return 0;
+ struct chunk *c;
+ struct file *f;
+ size_t page_mask;
+ size_t chunk_sz;
+ size_t size;
+
+ page_mask = get_page_mask();
+
+ list_for_each_entry(f, file_list, list) {
+ if (f->size <= min_chunk_sz)
+ chunk_sz = f->size;
+ else if (max_chunk_sz)
+ chunk_sz = max_chunk_sz;
+ else {
+ chunk_sz = (f->size - (f->size % nr_conn)) / nr_conn;
+ chunk_sz &= ~page_mask; /* align in page_sz */
+ if (chunk_sz <= min_chunk_sz)
+ chunk_sz = min_chunk_sz;
+ }
+
+ pr_debug("%s chunk_sz %lu-byte\n", f->path, chunk_sz);
+
+ for (size = f->size; size > 0;) {
+ c = chunk_alloc(f);
+ if (!c)
+ return -1;
+ c->off = f->size - size;
+ c->len = size < chunk_sz ? size : chunk_sz;
+ size -= c->len;
+ list_add_tail(&c->list, chunk_list);
+ pprint4("chunk %s 0x%010lx-0x%010lx %luB\n",
+ c->f->path, c->off, c->off + c->len, c->len);
+ }
+ }
+
+ return 0;
}
#ifdef DEBUG
void chunk_dump(struct list_head *chunk_list)
{
- struct chunk *c;
+ struct chunk *c;
- list_for_each_entry(c, chunk_list, list) {
- pr_debug("%s %s 0x%010lx-0x%010lx %lu-byte\n",
- c->f->path, c->f->remote ? "(remote)" : "(local)",
- c->off, c->off + c->len, c->len);
- }
+ list_for_each_entry(c, chunk_list, list) {
+ pr_debug("%s %s 0x%010lx-0x%010lx %lu-byte\n",
+ c->f->path, c->f->remote ? "(remote)" : "(local)",
+ c->off, c->off + c->len, c->len);
+ }
}
#endif
struct chunk *chunk_acquire(struct list_head *chunk_list)
{
- /* under the lock for chunk_list */
+ /* under the lock for chunk_list */
- struct list_head *first = chunk_list->next;
- struct chunk *c = NULL;
+ struct list_head *first = chunk_list->next;
+ struct chunk *c = NULL;
- if (list_empty(chunk_list))
- return NULL; /* list is empty */
+ if (list_empty(chunk_list))
+ return NULL; /* list is empty */
- c = list_entry(first, struct chunk, list);
- list_del(first);
- return c;
+ c = list_entry(first, struct chunk, list);
+ list_del(first);
+ return c;
}
int chunk_prepare(struct chunk *c, sftp_session sftp)
{
- struct file *f = c->f;
- int ret = 0;
-
- lock_acquire(&f->lock); /* XXX: is always acquiring lock per-chunk heavy? */
- if (f->state == FILE_STATE_INIT) {
- if (file_dst_prepare(f, f->dst_remote ? sftp : NULL) < 0) {
- ret = -1;
- goto out;
- }
- f->state = FILE_STATE_OPENED;
- pprint2("copy start: %s\n", f->path);
- }
+ struct file *f = c->f;
+ int ret = 0;
+
+ lock_acquire(&f->lock); /* XXX: is always acquiring lock per-chunk heavy? */
+ if (f->state == FILE_STATE_INIT) {
+ if (file_dst_prepare(f, f->dst_remote ? sftp : NULL) < 0) {
+ ret = -1;
+ goto out;
+ }
+ f->state = FILE_STATE_OPENED;
+ pprint2("copy start: %s\n", f->path);
+ }
out:
- lock_release(&f->lock);
- return ret;
+ lock_release(&f->lock);
+ return ret;
}
static mode_t chunk_get_mode(const char *path, sftp_session sftp)
{
- mode_t mode;
-
- if (sftp) {
- sftp_attributes attr = sftp_stat(sftp, path);
- if (!attr) {
- pr_err("failed to get stat for %s: %s\n",
- path, ssh_get_error(sftp_ssh(sftp)));
- return -1;
- }
- mode = attr->permissions;
- sftp_attributes_free(attr);
- } else {
- struct stat statbuf;
- if (stat(path, &statbuf) < 0) {
- pr_err("failed to get stat for %s: %s\n",
- path, strerrno());
- return -1;
- }
- mode = statbuf.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO);
- }
- return mode;
+ mode_t mode;
+
+ if (sftp) {
+ sftp_attributes attr = sftp_stat(sftp, path);
+ if (!attr) {
+ pr_err("failed to get stat for %s: %s\n",
+ path, ssh_get_error(sftp_ssh(sftp)));
+ return -1;
+ }
+ mode = attr->permissions;
+ sftp_attributes_free(attr);
+ } else {
+ struct stat statbuf;
+ if (stat(path, &statbuf) < 0) {
+ pr_err("failed to get stat for %s: %s\n",
+ path, strerrno());
+ return -1;
+ }
+ mode = statbuf.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO);
+ }
+ return mode;
}
static int chunk_set_mode(const char *path, mode_t mode, sftp_session sftp)
{
- if (sftp) {
- if (sftp_chmod(sftp, path, mode) < 0) {
- pr_err("failed to chmod %s: %s\n",
- path, ssh_get_error(sftp_ssh(sftp)));
- return -1;
- }
- } else {
- if (chmod(path, mode) < 0) {
- pr_err("failed to chmod %s: %s\n",
- path, strerrno());
- return -1;
- }
- }
-
- return 0;
+ if (sftp) {
+ if (sftp_chmod(sftp, path, mode) < 0) {
+ pr_err("failed to chmod %s: %s\n",
+ path, ssh_get_error(sftp_ssh(sftp)));
+ return -1;
+ }
+ } else {
+ if (chmod(path, mode) < 0) {
+ pr_err("failed to chmod %s: %s\n",
+ path, strerrno());
+ return -1;
+ }
+ }
+
+ return 0;
}
static int chunk_open_local(const char *path, int flags, mode_t mode, size_t off)
{
- int fd;
-
- fd = open(path, flags, mode);
- if (fd < 0) {
- pr_err("open failed for %s: %s\n", path, strerrno());
- return -1;
- }
- if (lseek(fd, off, SEEK_SET) < 0) {
- pr_err("seek error for %s: %s\n", path, strerrno());
- close(fd);
- return -1;
- }
-
- return fd;
+ int fd;
+
+ fd = open(path, flags, mode);
+ if (fd < 0) {
+ pr_err("open failed for %s: %s\n", path, strerrno());
+ return -1;
+ }
+ if (lseek(fd, off, SEEK_SET) < 0) {
+ pr_err("seek error for %s: %s\n", path, strerrno());
+ close(fd);
+ return -1;
+ }
+
+ return fd;
}
static sftp_file chunk_open_remote(const char *path, int flags, mode_t mode, size_t off,
- sftp_session sftp)
+ sftp_session sftp)
{
- sftp_file sf;
+ sftp_file sf;
- sf = sftp_open(sftp, path, flags, mode);
+ sf = sftp_open(sftp, path, flags, mode);
- if (!sf) {
- pr_err("open failed for remote %s: %s\n",
- path, ssh_get_error(sftp_ssh(sftp)));
- return NULL;
- }
+ if (!sf) {
+ pr_err("open failed for remote %s: %s\n",
+ path, ssh_get_error(sftp_ssh(sftp)));
+ return NULL;
+ }
- if (sftp_seek64(sf, off) < 0) {
- pr_err("seek error for %s: %s\n", path, ssh_get_error(sftp_ssh(sftp)));
- return NULL;
- }
+ if (sftp_seek64(sf, off) < 0) {
+ pr_err("seek error for %s: %s\n", path, ssh_get_error(sftp_ssh(sftp)));
+ return NULL;
+ }
- return sf;
+ return sf;
}
static int chunk_copy_internal(struct chunk *c, int fd, sftp_file sf,
- size_t sftp_buf_sz, size_t io_buf_sz,
- bool reverse, size_t *counter)
+ size_t sftp_buf_sz, size_t io_buf_sz,
+ bool reverse, size_t *counter)
{
- int remaind, read_bytes, write_bytes;
- char buf[io_buf_sz];
-
- /* if reverse is false, copy fd->sf (local to remote).
- * if reverse is true, copy sf->fd (remote to local)
- */
-
- for (remaind = c->len; remaind > 0;) {
-
- if (!reverse)
- read_bytes = read(fd, buf, min(remaind, io_buf_sz));
- else
- read_bytes = sftp_read2(sf, buf, min(remaind, io_buf_sz),
- sftp_buf_sz);
-
- if (read_bytes < 0) {
- pr_err("failed to read %s: %s\n", c->f->dst_path,
- !reverse ?
- strerrno() : ssh_get_error(sftp_ssh(sf->sftp)));
- return -1;
- }
-
- if (!reverse)
- write_bytes = sftp_write2(sf, buf, read_bytes, sftp_buf_sz);
- else
- write_bytes = write(fd, buf, read_bytes);
-
- if (write_bytes < 0) {
- pr_err("failed to write %s: %s\n", c->f->dst_path,
- !reverse ?
- strerrno() : ssh_get_error(sftp_ssh(sf->sftp)));
- return -1;
- }
-
- if (write_bytes < read_bytes) {
- pr_err("failed to write full bytes to %s\n", c->f->dst_path);
- return -1;
- }
-
- *counter += write_bytes;
- remaind -= write_bytes;
- }
-
- return 0;
+ int remaind, read_bytes, write_bytes;
+ char buf[io_buf_sz];
+
+ /* if reverse is false, copy fd->sf (local to remote).
+ * if reverse is true, copy sf->fd (remote to local)
+ */
+
+ for (remaind = c->len; remaind > 0;) {
+
+ if (!reverse)
+ read_bytes = read(fd, buf, min(remaind, io_buf_sz));
+ else
+ read_bytes = sftp_read2(sf, buf, min(remaind, io_buf_sz),
+ sftp_buf_sz);
+
+ if (read_bytes < 0) {
+ pr_err("failed to read %s: %s\n", c->f->dst_path,
+ !reverse ?
+ strerrno() : ssh_get_error(sftp_ssh(sf->sftp)));
+ return -1;
+ }
+
+ if (!reverse)
+ write_bytes = sftp_write2(sf, buf, read_bytes, sftp_buf_sz);
+ else
+ write_bytes = write(fd, buf, read_bytes);
+
+ if (write_bytes < 0) {
+ pr_err("failed to write %s: %s\n", c->f->dst_path,
+ !reverse ?
+ strerrno() : ssh_get_error(sftp_ssh(sf->sftp)));
+ return -1;
+ }
+
+ if (write_bytes < read_bytes) {
+ pr_err("failed to write full bytes to %s\n", c->f->dst_path);
+ return -1;
+ }
+
+ *counter += write_bytes;
+ remaind -= write_bytes;
+ }
+
+ return 0;
}
static int chunk_copy_local_to_remote(struct chunk *c, sftp_session sftp,
- size_t sftp_buf_sz, size_t io_buf_sz,
- size_t *counter)
+ size_t sftp_buf_sz, size_t io_buf_sz,
+ size_t *counter)
{
- struct file *f = c->f;
- sftp_file sf = NULL;
- mode_t mode;
- int ret = 0;
- int fd = 0;
- int flags;
-
- flags = O_RDONLY;
- mode = S_IRUSR;
- if ((fd = chunk_open_local(f->path, flags, mode, c->off)) < 0) {
- ret = -1;
- goto out;
- }
-
- flags = O_WRONLY|O_CREAT;
- mode = S_IRUSR|S_IWUSR;
- if (!(sf = chunk_open_remote(f->dst_path, flags, mode, c->off, sftp))) {
- ret = -1;
- goto out;
- }
-
- ret = chunk_copy_internal(c, fd, sf, sftp_buf_sz, io_buf_sz, false, counter);
- if (ret< 0)
- goto out;
-
- if ((mode = chunk_get_mode(f->path, NULL)) < 0) {
- ret = -1;
- goto out;
- }
- if (chunk_set_mode(f->dst_path, mode, sftp) < 0) {
- ret = -1;
- }
+ struct file *f = c->f;
+ sftp_file sf = NULL;
+ mode_t mode;
+ int ret = 0;
+ int fd = 0;
+ int flags;
+
+ flags = O_RDONLY;
+ mode = S_IRUSR;
+ if ((fd = chunk_open_local(f->path, flags, mode, c->off)) < 0) {
+ ret = -1;
+ goto out;
+ }
+
+ flags = O_WRONLY|O_CREAT;
+ mode = S_IRUSR|S_IWUSR;
+ if (!(sf = chunk_open_remote(f->dst_path, flags, mode, c->off, sftp))) {
+ ret = -1;
+ goto out;
+ }
+
+ ret = chunk_copy_internal(c, fd, sf, sftp_buf_sz, io_buf_sz, false, counter);
+ if (ret< 0)
+ goto out;
+
+ if ((mode = chunk_get_mode(f->path, NULL)) < 0) {
+ ret = -1;
+ goto out;
+ }
+ if (chunk_set_mode(f->dst_path, mode, sftp) < 0) {
+ ret = -1;
+ }
out:
- if (fd > 0)
- close(fd);
- if (sf)
- sftp_close(sf);
- return ret;
+ if (fd > 0)
+ close(fd);
+ if (sf)
+ sftp_close(sf);
+ return ret;
}
static int chunk_copy_remote_to_local(struct chunk *c, sftp_session sftp,
- size_t sftp_buf_sz, size_t io_buf_sz,
- size_t *counter)
+ size_t sftp_buf_sz, size_t io_buf_sz,
+ size_t *counter)
{
- struct file *f = c->f;
- sftp_file sf = NULL;
- mode_t mode;
- int flags;
- int fd = 0;
- int ret = 0;
-
- flags = O_WRONLY|O_CREAT;
- mode = S_IRUSR|S_IWUSR;
- if ((fd = chunk_open_local(f->dst_path, flags, mode, c->off)) < 0) {
- ret = -1;
- goto out;
- }
-
- flags = O_RDONLY;
- mode = S_IRUSR;
- if (!(sf = chunk_open_remote(f->path, flags, mode, c->off, sftp))) {
- ret = -1;
- goto out;
- }
-
- ret = chunk_copy_internal(c, fd, sf, sftp_buf_sz, io_buf_sz, true, counter);
- if (ret< 0)
- goto out;
+ struct file *f = c->f;
+ sftp_file sf = NULL;
+ mode_t mode;
+ int flags;
+ int fd = 0;
+ int ret = 0;
+
+ flags = O_WRONLY|O_CREAT;
+ mode = S_IRUSR|S_IWUSR;
+ if ((fd = chunk_open_local(f->dst_path, flags, mode, c->off)) < 0) {
+ ret = -1;
+ goto out;
+ }
+
+ flags = O_RDONLY;
+ mode = S_IRUSR;
+ if (!(sf = chunk_open_remote(f->path, flags, mode, c->off, sftp))) {
+ ret = -1;
+ goto out;
+ }
+
+ ret = chunk_copy_internal(c, fd, sf, sftp_buf_sz, io_buf_sz, true, counter);
+ if (ret< 0)
+ goto out;
out:
- if (fd > 0)
- close(fd);
- if (sf)
- sftp_close(sf);
+ if (fd > 0)
+ close(fd);
+ if (sf)
+ sftp_close(sf);
- return ret;
+ return ret;
}
int chunk_copy(struct chunk *c, sftp_session sftp, size_t sftp_buf_sz, size_t io_buf_sz,
- size_t *counter)
+ size_t *counter)
{
- struct file *f = c->f;
- int ret = 0;
+ struct file *f = c->f;
+ int ret = 0;
- pr_debug("copy %s %s -> %s %s off=0x%010lx\n",
- f->path, f->remote ? "(remote)" : "(local)",
- f->dst_path, f->dst_remote ? "(remote)" : "(local)", c->off);
+ pr_debug("copy %s %s -> %s %s off=0x%010lx\n",
+ f->path, f->remote ? "(remote)" : "(local)",
+ f->dst_path, f->dst_remote ? "(remote)" : "(local)", c->off);
- pprint4("copy start: chunk %s 0x%010lx-0x%010lx %luB\n",
- c->f->path, c->off, c->off + c->len, c->len);
+ pprint4("copy start: chunk %s 0x%010lx-0x%010lx %luB\n",
+ c->f->path, c->off, c->off + c->len, c->len);
- if (f->dst_remote)
- ret = chunk_copy_local_to_remote(c, sftp,
- sftp_buf_sz, io_buf_sz, counter);
- else
- ret = chunk_copy_remote_to_local(c, sftp,
- sftp_buf_sz, io_buf_sz, counter);
+ if (f->dst_remote)
+ ret = chunk_copy_local_to_remote(c, sftp,
+ sftp_buf_sz, io_buf_sz, counter);
+ else
+ ret = chunk_copy_remote_to_local(c, sftp,
+ sftp_buf_sz, io_buf_sz, counter);
- if (ret < 0)
- return ret;
+ if (ret < 0)
+ return ret;
- pr_debug("done %s %s -> %s %s off=0x%010lx\n",
- f->path, f->remote ? "(remote)" : "(local)",
- f->dst_path, f->dst_remote ? "(remote)" : "(local)", c->off);
+ pr_debug("done %s %s -> %s %s off=0x%010lx\n",
+ f->path, f->remote ? "(remote)" : "(local)",
+ f->dst_path, f->dst_remote ? "(remote)" : "(local)", c->off);
- pprint4("copy done: chunk %s 0x%010lx-0x%010lx %luB\n",
- c->f->path, c->off, c->off + c->len, c->len);
+ pprint4("copy done: chunk %s 0x%010lx-0x%010lx %luB\n",
+ c->f->path, c->off, c->off + c->len, c->len);
- if (refcnt_dec(&f->refcnt) == 0) {
- f->state = FILE_STATE_DONE;
- pprint2("copy done: %s\n", f->path);
- }
+ if (refcnt_dec(&f->refcnt) == 0) {
+ f->state = FILE_STATE_DONE;
+ pprint2("copy done: %s\n", f->path);
+ }
- return ret;
+ return ret;
}
diff --git a/src/file.h b/src/file.h
index e257bcd..094057b 100644
--- a/src/file.h
+++ b/src/file.h
@@ -10,18 +10,18 @@
#include <atomic.h>
struct file {
- struct list_head list; /* sscp->file_list */
+ struct list_head list; /* sscp->file_list */
- char path[PATH_MAX]; /* copy source path */
- bool remote; /* source is remote */
- size_t size; /* size of this file */
+ char path[PATH_MAX]; /* copy source path */
+ bool remote; /* source is remote */
+ size_t size; /* size of this file */
- char dst_path[PATH_MAX]; /* copy destination path */
- bool dst_remote; /* destination is remote */
+ char dst_path[PATH_MAX]; /* copy destination path */
+ bool dst_remote; /* destination is remote */
- int state; /* destination file state */
- lock lock; /* mutex to protect state */
- refcnt refcnt; /* chunks referencing this file */
+ int state; /* destination file state */
+ lock lock; /* mutex to protect state */
+ refcnt refcnt; /* chunks referencing this file */
};
#define FILE_STATE_INIT 0
#define FILE_STATE_OPENED 1
@@ -51,26 +51,26 @@ struct file {
*/
struct chunk {
- struct list_head list; /* sscp->chunk_list */
- struct file *f;
- size_t off; /* offset of this chunk on the file f */
- size_t len; /* length of this chunk */
- size_t done; /* copied bytes for this chunk by a thread */
+ struct list_head list; /* sscp->chunk_list */
+ struct file *f;
+ size_t off; /* offset of this chunk on the file f */
+ size_t len; /* length of this chunk */
+ size_t done; /* copied bytes for this chunk by a thread */
};
char *file_find_hostname(char *path);
bool file_has_hostname(char *path);
int file_fill(sftp_session sftp, struct list_head *file_list, char **src_array, int cnt,
- char *dst);
+ char *dst);
int chunk_fill(struct list_head *file_list, struct list_head *chunk_list,
- int nr_conn, int min_chunk_sz, int max_chunk_sz);
+ int nr_conn, int min_chunk_sz, int max_chunk_sz);
struct chunk *chunk_acquire(struct list_head *chunk_list);
int chunk_prepare(struct chunk *c, sftp_session sftp);
int chunk_copy(struct chunk *c, sftp_session sftp,
- size_t sftp_buf_sz, size_t io_buf_sz, size_t *counter);
+ size_t sftp_buf_sz, size_t io_buf_sz, size_t *counter);
#ifdef DEBUG
void file_dump(struct list_head *file_list);
diff --git a/src/main.c b/src/main.c
index 1fbf462..e8bf8b4 100644
--- a/src/main.c
+++ b/src/main.c
@@ -22,28 +22,28 @@
/* XXX: need to investigate max buf size for sftp_read/sftp_write */
struct sscp {
- char *host; /* remote host (and username) */
- struct ssh_opts *opts; /* ssh parameters */
- sftp_session ctrl; /* control sftp session */
+ char *host; /* remote host (and username) */
+ struct ssh_opts *opts; /* ssh parameters */
+ sftp_session ctrl; /* control sftp session */
- struct list_head file_list;
- struct list_head chunk_list; /* stack of chunks */
- lock chunk_lock; /* lock for chunk list */
+ struct list_head file_list;
+ struct list_head chunk_list; /* stack of chunks */
+ lock chunk_lock; /* lock for chunk list */
- char *target;
+ char *target;
- int sftp_buf_sz, io_buf_sz;
+ int sftp_buf_sz, io_buf_sz;
- struct timeval start; /* timestamp of starting copy */
+ struct timeval start; /* timestamp of starting copy */
};
struct sscp_thread {
- struct sscp *sscp;
- sftp_session sftp;
+ struct sscp *sscp;
+ sftp_session sftp;
- pthread_t tid;
- size_t done; /* copied bytes */
- bool finished;
+ pthread_t tid;
+ size_t done; /* copied bytes */
+ bool finished;
};
void *sscp_copy_thread(void *arg);
@@ -55,175 +55,175 @@ int nr_threads;
void stop_copy_threads(int sig)
{
- int n;
+ int n;
- pr("stopping...\n");
- for (n = 0; n < nr_threads; n++) {
- pthread_cancel(threads[n].tid);
- }
+ pr("stopping...\n");
+ for (n = 0; n < nr_threads; n++) {
+ pthread_cancel(threads[n].tid);
+ }
}
void usage(bool print_help) {
- printf("sscp: super scp, copy files over multiple ssh connections\n"
- "\n"
- "Usage: sscp [CvqDdh] [-n nr_conns] [-s min_chunk_sz] [-S max_chunk_sz]\n"
- " [-b sftp_buf_sz] [-B io_buf_sz]\n"
- " [-l login_name] [-p port] [-i identity_file]\n"
- " [-c cipher_spec] source ... target\n"
- "\n");
-
- if (!print_help)
- return;
-
- printf(" -n NR_CONNECTIONS number of connections (default: half of # of cpu cores)\n"
- " -s MIN_CHUNK_SIZE min chunk size (default: 64MB)\n"
- " -S MAX_CHUNK_SIZE max chunk size (default: filesize / nr_conn)\n"
- " -b SFTP_BUF_SIZE buf size for sftp_read/write (default 131072B)\n"
- " -B IO_BUF_SIZE buf size for read/write (default 131072B)\n"
- " Note that this value is derived from\n"
- " qemu/block/ssh.c. need investigation...\n"
- " -v increment verbose output level\n"
- " -q disable output\n"
- " -D dry run\n"
- "\n"
- " -l LOGIN_NAME login name\n"
- " -p PORT port number\n"
- " -i IDENTITY identity file for publickey authentication\n"
- " -c CIPHER cipher spec, see `ssh -Q cipher`\n"
- " -C enable compression on libssh\n"
- " -d increment ssh debug output level\n"
- " -h print this help\n"
- "\n");
+ printf("sscp: super scp, copy files over multiple ssh connections\n"
+ "\n"
+ "Usage: sscp [CvqDdh] [-n nr_conns] [-s min_chunk_sz] [-S max_chunk_sz]\n"
+ " [-b sftp_buf_sz] [-B io_buf_sz]\n"
+ " [-l login_name] [-p port] [-i identity_file]\n"
+ " [-c cipher_spec] source ... target\n"
+ "\n");
+
+ if (!print_help)
+ return;
+
+ printf(" -n NR_CONNECTIONS number of connections (default: half of # of cpu cores)\n"
+ " -s MIN_CHUNK_SIZE min chunk size (default: 64MB)\n"
+ " -S MAX_CHUNK_SIZE max chunk size (default: filesize / nr_conn)\n"
+ " -b SFTP_BUF_SIZE buf size for sftp_read/write (default 131072B)\n"
+ " -B IO_BUF_SIZE buf size for read/write (default 131072B)\n"
+ " Note that this value is derived from\n"
+ " qemu/block/ssh.c. need investigation...\n"
+ " -v increment verbose output level\n"
+ " -q disable output\n"
+ " -D dry run\n"
+ "\n"
+ " -l LOGIN_NAME login name\n"
+ " -p PORT port number\n"
+ " -i IDENTITY identity file for publickey authentication\n"
+ " -c CIPHER cipher spec, see `ssh -Q cipher`\n"
+ " -C enable compression on libssh\n"
+ " -d increment ssh debug output level\n"
+ " -h print this help\n"
+ "\n");
}
char *find_hostname(int ind, int argc, char **argv)
{
- char *h, *hostnames[argc];
- int n, cnt = 0;
-
- for (n = ind; n < argc; n++) {
- h = file_find_hostname(argv[n]);
- if (h)
- hostnames[cnt++] = h;
- }
-
- if (cnt == 0)
- return NULL;
-
- /* check all hostnames are identical */
- for (n = 1; n < cnt; n++) {
- int s1 = strlen(hostnames[n - 1]);
- int s2 = strlen(hostnames[n]);
- if (s1 != s2) {
- pr_err("different hostnames: %s and %s\n",
- hostnames[n - 1], hostnames[n]);
- goto err_out;
- }
- if (strncmp(hostnames[n - 1], hostnames[n], s1) != 0) {
- pr_err("different hostnames: %s and %s\n",
- hostnames[n - 1], hostnames[n]);
- goto err_out;
- }
- }
-
- for (n = 1; n < cnt; n++) {
- free(hostnames[n]);
- }
-
- return hostnames[0];
+ char *h, *hostnames[argc];
+ int n, cnt = 0;
+
+ for (n = ind; n < argc; n++) {
+ h = file_find_hostname(argv[n]);
+ if (h)
+ hostnames[cnt++] = h;
+ }
+
+ if (cnt == 0)
+ return NULL;
+
+ /* check all hostnames are identical */
+ for (n = 1; n < cnt; n++) {
+ int s1 = strlen(hostnames[n - 1]);
+ int s2 = strlen(hostnames[n]);
+ if (s1 != s2) {
+ pr_err("different hostnames: %s and %s\n",
+ hostnames[n - 1], hostnames[n]);
+ goto err_out;
+ }
+ if (strncmp(hostnames[n - 1], hostnames[n], s1) != 0) {
+ pr_err("different hostnames: %s and %s\n",
+ hostnames[n - 1], hostnames[n]);
+ goto err_out;
+ }
+ }
+
+ for (n = 1; n < cnt; n++) {
+ free(hostnames[n]);
+ }
+
+ return hostnames[0];
err_out:
- for (n = 0; n < cnt; n++) {
- free(hostnames[n]);
- }
- return NULL;
+ for (n = 0; n < cnt; n++) {
+ free(hostnames[n]);
+ }
+ return NULL;
}
int main(int argc, char **argv)
{
- struct sscp sscp;
+ struct sscp sscp;
struct ssh_opts opts;
- int min_chunk_sz = DEFAULT_MIN_CHUNK_SZ;
- int max_chunk_sz = 0;
- int verbose = 1;
- bool dryrun = false;
- int ret = 0, n;
- char ch;
-
- memset(&opts, 0, sizeof(opts));
- memset(&sscp, 0, sizeof(sscp));
- INIT_LIST_HEAD(&sscp.file_list);
- INIT_LIST_HEAD(&sscp.chunk_list);
- lock_init(&sscp.chunk_lock);
- sscp.sftp_buf_sz = DEFAULT_SFTP_BUF_SZ;
- sscp.io_buf_sz = DEFAULT_IO_BUF_SZ;
-
- nr_threads = (int)(nr_cpus() / 2);
- nr_threads = nr_threads == 0 ? 1 : nr_threads;
+ int min_chunk_sz = DEFAULT_MIN_CHUNK_SZ;
+ int max_chunk_sz = 0;
+ int verbose = 1;
+ bool dryrun = false;
+ int ret = 0, n;
+ char ch;
+
+ memset(&opts, 0, sizeof(opts));
+ memset(&sscp, 0, sizeof(sscp));
+ INIT_LIST_HEAD(&sscp.file_list);
+ INIT_LIST_HEAD(&sscp.chunk_list);
+ lock_init(&sscp.chunk_lock);
+ sscp.sftp_buf_sz = DEFAULT_SFTP_BUF_SZ;
+ sscp.io_buf_sz = DEFAULT_IO_BUF_SZ;
+
+ nr_threads = (int)(nr_cpus() / 2);
+ nr_threads = nr_threads == 0 ? 1 : nr_threads;
while ((ch = getopt(argc, argv, "n:s:S:b:B:vqDl:p:i:c:Cdh")) != -1) {
switch (ch) {
- case 'n':
- nr_threads = atoi(optarg);
- if (nr_threads < 1) {
- pr_err("invalid number of connections: %s\n", optarg);
- return 1;
- }
- break;
- case 's':
- min_chunk_sz = atoi(optarg);
- if (min_chunk_sz < getpagesize()) {
- pr_err("min chunk size must be "
- "larger than or equal to %d: %s\n",
- getpagesize(), optarg);
- return 1;
- }
- if (min_chunk_sz % getpagesize() != 0) {
- pr_err("min chunk size must be "
- "multiple of page size %d: %s\n",
- getpagesize(), optarg);
- return -1;
- }
- break;
- case 'S':
- max_chunk_sz = atoi(optarg);
- if (max_chunk_sz < getpagesize()) {
- pr_err("max chunk size must be "
- "larger than or equal to %d: %s\n",
- getpagesize(), optarg);
- return 1;
- }
- if (max_chunk_sz % getpagesize() != 0) {
- pr_err("max chunk size must be "
- "multiple of page size %d: %s\n",
- getpagesize(), optarg);
- return -1;
- }
- break;
- case 'b':
- sscp.sftp_buf_sz = atoi(optarg);
- if (sscp.sftp_buf_sz < 1) {
- pr_err("invalid buffer size: %s\n", optarg);
- return -1;
- }
- break;
- case 'B':
- sscp.io_buf_sz = atoi(optarg);
- if (sscp.io_buf_sz < 1) {
- pr_err("invalid buffer size: %s\n", optarg);
- return -1;
- }
- break;
- case 'v':
- verbose++;
- break;
- case 'q':
- verbose = -1;
- break;
- case 'D':
- dryrun = true;
- break;
+ case 'n':
+ nr_threads = atoi(optarg);
+ if (nr_threads < 1) {
+ pr_err("invalid number of connections: %s\n", optarg);
+ return 1;
+ }
+ break;
+ case 's':
+ min_chunk_sz = atoi(optarg);
+ if (min_chunk_sz < getpagesize()) {
+ pr_err("min chunk size must be "
+ "larger than or equal to %d: %s\n",
+ getpagesize(), optarg);
+ return 1;
+ }
+ if (min_chunk_sz % getpagesize() != 0) {
+ pr_err("min chunk size must be "
+ "multiple of page size %d: %s\n",
+ getpagesize(), optarg);
+ return -1;
+ }
+ break;
+ case 'S':
+ max_chunk_sz = atoi(optarg);
+ if (max_chunk_sz < getpagesize()) {
+ pr_err("max chunk size must be "
+ "larger than or equal to %d: %s\n",
+ getpagesize(), optarg);
+ return 1;
+ }
+ if (max_chunk_sz % getpagesize() != 0) {
+ pr_err("max chunk size must be "
+ "multiple of page size %d: %s\n",
+ getpagesize(), optarg);
+ return -1;
+ }
+ break;
+ case 'b':
+ sscp.sftp_buf_sz = atoi(optarg);
+ if (sscp.sftp_buf_sz < 1) {
+ pr_err("invalid buffer size: %s\n", optarg);
+ return -1;
+ }
+ break;
+ case 'B':
+ sscp.io_buf_sz = atoi(optarg);
+ if (sscp.io_buf_sz < 1) {
+ pr_err("invalid buffer size: %s\n", optarg);
+ return -1;
+ }
+ break;
+ case 'v':
+ verbose++;
+ break;
+ case 'q':
+ verbose = -1;
+ break;
+ case 'D':
+ dryrun = true;
+ break;
case 'l':
opts.login_name = optarg;
break;
@@ -242,322 +242,322 @@ int main(int argc, char **argv)
case 'd':
opts.debuglevel++;
break;
- case 'h':
- usage(true);
- return 1;
- default:
- usage(false);
- return 1;
+ case 'h':
+ usage(true);
+ return 1;
+ default:
+ usage(false);
+ return 1;
}
- }
-
- pprint_set_level(verbose);
-
- if (max_chunk_sz > 0 && min_chunk_sz > max_chunk_sz) {
- pr_err("smaller max chunk size than min chunk size: %d < %d\n",
- max_chunk_sz, min_chunk_sz);
- return 1;
- }
-
- if (argc - optind < 2) {
- /* sscp needs at lease 2 (src and target) argument */
- usage(false);
- return 1;
- }
-
- sscp.target = argv[argc - 1];
-
- /* create control session */
- sscp.host = find_hostname(optind, argc, argv);
- if (!sscp.host) {
- pr_err("no remote host given\n");
- return 1;
- }
- pprint3("connecting to %s for checking destinations...\n", sscp.host);
- sscp.ctrl = ssh_make_sftp_session(sscp.host, &opts);
- if (!sscp.ctrl)
- return 1;
- sscp.opts = &opts; /* save ssh-able ssh_opts */
-
-
- /* fill file list */
- ret = file_fill(sscp.ctrl, &sscp.file_list, &argv[optind], argc - optind - 1,
- sscp.target);
- if (ret < 0)
- goto out;
+ }
+
+ pprint_set_level(verbose);
+
+ if (max_chunk_sz > 0 && min_chunk_sz > max_chunk_sz) {
+ pr_err("smaller max chunk size than min chunk size: %d < %d\n",
+ max_chunk_sz, min_chunk_sz);
+ return 1;
+ }
+
+ if (argc - optind < 2) {
+ /* sscp needs at lease 2 (src and target) argument */
+ usage(false);
+ return 1;
+ }
+
+ sscp.target = argv[argc - 1];
+
+ /* create control session */
+ sscp.host = find_hostname(optind, argc, argv);
+ if (!sscp.host) {
+ pr_err("no remote host given\n");
+ return 1;
+ }
+ pprint3("connecting to %s for checking destinations...\n", sscp.host);
+ sscp.ctrl = ssh_make_sftp_session(sscp.host, &opts);
+ if (!sscp.ctrl)
+ return 1;
+ sscp.opts = &opts; /* save ssh-able ssh_opts */
+
+
+ /* fill file list */
+ ret = file_fill(sscp.ctrl, &sscp.file_list, &argv[optind], argc - optind - 1,
+ sscp.target);
+ if (ret < 0)
+ goto out;
#ifdef DEBUG
- file_dump(&sscp.file_list);
+ file_dump(&sscp.file_list);
#endif
- /* fill chunk list */
- ret = chunk_fill(&sscp.file_list, &sscp.chunk_list,
- nr_threads, min_chunk_sz, max_chunk_sz);
- if (ret < 0)
- goto out;
+ /* fill chunk list */
+ ret = chunk_fill(&sscp.file_list, &sscp.chunk_list,
+ nr_threads, min_chunk_sz, max_chunk_sz);
+ if (ret < 0)
+ goto out;
#ifdef DEBUG
- chunk_dump(&sscp.chunk_list);
+ chunk_dump(&sscp.chunk_list);
#endif
- if (dryrun)
- return 0;
-
- /* register SIGINT to stop thrads */
- if (signal(SIGINT, stop_copy_threads) == SIG_ERR) {
- pr_err("cannot set signal: %s\n", strerrno());
- ret = 1;
- goto out;
- }
-
- /* prepare thread instances */
- threads = calloc(nr_threads, sizeof(struct sscp_thread));
- memset(threads, 0, nr_threads * sizeof(struct sscp_thread));
- for (n = 0; n < nr_threads; n++) {
- struct sscp_thread *t = &threads[n];
- t->sscp = &sscp;
- t->finished = false;
- pprint3("connecting to %s for a copy thread...\n", sscp.host);
- t->sftp = ssh_make_sftp_session(sscp.host, sscp.opts);
- if (!t->sftp)
- goto join_out;
- }
-
- /* spawn count thread */
- ret = pthread_create(&mtid, NULL, sscp_monitor_thread, &sscp);
- if (ret < 0) {
- pr_err("pthread_create error: %d\n", ret);
- stop_copy_threads(0);
- goto join_out;
- }
-
- /* save start time */
- gettimeofday(&sscp.start, NULL);
-
- /* spawn threads */
- for (n = 0; n < nr_threads; n++) {
- struct sscp_thread *t = &threads[n];
- ret = pthread_create(&t->tid, NULL, sscp_copy_thread, t);
- if (ret < 0) {
- pr_err("pthread_create error: %d\n", ret);
- stop_copy_threads(0);
- goto join_out;
- }
- }
+ if (dryrun)
+ return 0;
+
+ /* register SIGINT to stop thrads */
+ if (signal(SIGINT, stop_copy_threads) == SIG_ERR) {
+ pr_err("cannot set signal: %s\n", strerrno());
+ ret = 1;
+ goto out;
+ }
+
+ /* prepare thread instances */
+ threads = calloc(nr_threads, sizeof(struct sscp_thread));
+ memset(threads, 0, nr_threads * sizeof(struct sscp_thread));
+ for (n = 0; n < nr_threads; n++) {
+ struct sscp_thread *t = &threads[n];
+ t->sscp = &sscp;
+ t->finished = false;
+ pprint3("connecting to %s for a copy thread...\n", sscp.host);
+ t->sftp = ssh_make_sftp_session(sscp.host, sscp.opts);
+ if (!t->sftp)
+ goto join_out;
+ }
+
+ /* spawn count thread */
+ ret = pthread_create(&mtid, NULL, sscp_monitor_thread, &sscp);
+ if (ret < 0) {
+ pr_err("pthread_create error: %d\n", ret);
+ stop_copy_threads(0);
+ goto join_out;
+ }
+
+ /* save start time */
+ gettimeofday(&sscp.start, NULL);
+
+ /* spawn threads */
+ for (n = 0; n < nr_threads; n++) {
+ struct sscp_thread *t = &threads[n];
+ ret = pthread_create(&t->tid, NULL, sscp_copy_thread, t);
+ if (ret < 0) {
+ pr_err("pthread_create error: %d\n", ret);
+ stop_copy_threads(0);
+ goto join_out;
+ }
+ }
join_out:
- /* waiting for threads join... */
- for (n = 0; n < nr_threads; n++)
- if (threads[n].tid)
- pthread_join(threads[n].tid, NULL);
+ /* waiting for threads join... */
+ for (n = 0; n < nr_threads; n++)
+ if (threads[n].tid)
+ pthread_join(threads[n].tid, NULL);
- if (mtid != 0) {
- pthread_cancel(mtid);
- pthread_join(mtid, NULL);
- }
+ if (mtid != 0) {
+ pthread_cancel(mtid);
+ pthread_join(mtid, NULL);
+ }
out:
- if (sscp.ctrl)
- ssh_sftp_close(sscp.ctrl);
+ if (sscp.ctrl)
+ ssh_sftp_close(sscp.ctrl);
return ret;
}
void sscp_copy_thread_cleanup(void *arg)
{
- struct sscp_thread *t = arg;
- if (t->sftp)
- ssh_sftp_close(t->sftp);
- t->finished = true;
+ struct sscp_thread *t = arg;
+ if (t->sftp)
+ ssh_sftp_close(t->sftp);
+ t->finished = true;
}
void *sscp_copy_thread(void *arg)
{
- struct sscp_thread *t = arg;
- struct sscp *sscp = t->sscp;
- sftp_session sftp = t->sftp;
- struct chunk *c;
+ struct sscp_thread *t = arg;
+ struct sscp *sscp = t->sscp;
+ sftp_session sftp = t->sftp;
+ struct chunk *c;
- pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
- pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
- pthread_cleanup_push(sscp_copy_thread_cleanup, t);
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+ pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
+ pthread_cleanup_push(sscp_copy_thread_cleanup, t);
- while (1) {
- lock_acquire(&sscp->chunk_lock);
- c = chunk_acquire(&sscp->chunk_list);
- lock_release(&sscp->chunk_lock);
+ while (1) {
+ lock_acquire(&sscp->chunk_lock);
+ c = chunk_acquire(&sscp->chunk_list);
+ lock_release(&sscp->chunk_lock);
- if (!c)
- break; /* no more chunks */
+ if (!c)
+ break; /* no more chunks */
- if (chunk_prepare(c, sftp) < 0)
- break;
+ if (chunk_prepare(c, sftp) < 0)
+ break;
- if (chunk_copy(c, sftp,
- sscp->sftp_buf_sz, sscp->io_buf_sz, &t->done) < 0)
- break;
- }
+ if (chunk_copy(c, sftp,
+ sscp->sftp_buf_sz, sscp->io_buf_sz, &t->done) < 0)
+ break;
+ }
- pthread_cleanup_pop(1);
+ pthread_cleanup_pop(1);
- return NULL;
+ return NULL;
}
static double calculate_bps(size_t diff, struct timeval *b, struct timeval *a)
{
- double sec, usec;
+ double sec, usec;
- if (a->tv_usec < b->tv_usec) {
- a->tv_usec += 1000000;
- a->tv_sec--;
- }
+ if (a->tv_usec < b->tv_usec) {
+ a->tv_usec += 1000000;
+ a->tv_sec--;
+ }
- sec = a->tv_sec - b->tv_sec;
- usec = a->tv_usec - b->tv_usec;
- sec += usec / 1000000;
+ sec = a->tv_sec - b->tv_sec;
+ usec = a->tv_usec - b->tv_usec;
+ sec += usec / 1000000;
- return (double)diff / sec;
+ return (double)diff / sec;
}
static void print_progress_bar(double percent, char *suffix)
{
- int n, thresh, bar_width;
- struct winsize ws;
- char buf[128];
-
- /*
- * [=======> ] XX.X% SUFFIX
- */
-
- buf[0] = '\0';
-
- if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) < 0)
- return; /* XXX */
- bar_width = min(sizeof(buf), ws.ws_col) - strlen(suffix) - 8;
-
- if (bar_width > 8) {
- memset(buf, 0, sizeof(buf));
- thresh = floor(bar_width * (percent / 100)) - 1;
-
- for (n = 1; n < bar_width - 1; n++) {
- if (n <= thresh)
- buf[n] = '=';
- else
- buf[n] = ' ';
- }
- buf[thresh] = '>';
- buf[0] = '[';
- buf[bar_width - 1] = ']';
- snprintf(buf + bar_width, sizeof(buf) - bar_width,
- " %3d%% ", (int)floor(percent));
- }
-
- pprint1("%s%s", buf, suffix);
+ int n, thresh, bar_width;
+ struct winsize ws;
+ char buf[128];
+
+/*
+ * [=======> ] XX.X% SUFFIX
+ */
+
+ buf[0] = '\0';
+
+ if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) < 0)
+ return; /* XXX */
+ bar_width = min(sizeof(buf), ws.ws_col) - strlen(suffix) - 8;
+
+ if (bar_width > 8) {
+ memset(buf, 0, sizeof(buf));
+ thresh = floor(bar_width * (percent / 100)) - 1;
+
+ for (n = 1; n < bar_width - 1; n++) {
+ if (n <= thresh)
+ buf[n] = '=';
+ else
+ buf[n] = ' ';
+ }
+ buf[thresh] = '>';
+ buf[0] = '[';
+ buf[bar_width - 1] = ']';
+ snprintf(buf + bar_width, sizeof(buf) - bar_width,
+ " %3d%% ", (int)floor(percent));
+ }
+
+ pprint1("%s%s", buf, suffix);
}
static void print_progress(struct timeval *start, struct timeval *end,
- size_t total, size_t last, size_t done)
+ size_t total, size_t last, size_t done)
{
- char *bps_units[] = { "B/s", "KB/s", "MB/s", "GB/s" };
- char *byte_units[] = { "B", "KB", "MB", "GB", "TB", "PB" };
- char suffix[128];
- int bps_u, byte_tu, byte_du;
- size_t total_round;
- int percent;
- double bps;
+ char *bps_units[] = { "B/s", "KB/s", "MB/s", "GB/s" };
+ char *byte_units[] = { "B", "KB", "MB", "GB", "TB", "PB" };
+ char suffix[128];
+ int bps_u, byte_tu, byte_du;
+ size_t total_round;
+ int percent;
+ double bps;
#define array_size(a) (sizeof(a) / sizeof(a[0]))
- total_round = total;
- for (byte_tu = 0; total_round > 1000 && byte_tu < array_size(byte_units) - 1;
- byte_tu++)
- total_round /= 1024;
+ total_round = total;
+ for (byte_tu = 0; total_round > 1000 && byte_tu < array_size(byte_units) - 1;
+ byte_tu++)
+ total_round /= 1024;
- bps = calculate_bps(done - last, start, end);
- for (bps_u = 0; bps > 1000 && bps_u < array_size(bps_units); bps_u++)
- bps /= 1000;
+ bps = calculate_bps(done - last, start, end);
+ for (bps_u = 0; bps > 1000 && bps_u < array_size(bps_units); bps_u++)
+ bps /= 1000;
- percent = floor(((double)(done) / (double)total) * 100);
- for (byte_du = 0; done > 1000 && byte_du < array_size(byte_units) - 1; byte_du++)
- done /= 1024;
+ percent = floor(((double)(done) / (double)total) * 100);
+ for (byte_du = 0; done > 1000 && byte_du < array_size(byte_units) - 1; byte_du++)
+ done /= 1024;
- snprintf(suffix, sizeof(suffix), "%lu%s/%lu%s %.2f%s ",
- done, byte_units[byte_du], total_round, byte_units[byte_tu],
- bps, bps_units[bps_u]);
+ snprintf(suffix, sizeof(suffix), "%lu%s/%lu%s %.2f%s ",
+ done, byte_units[byte_du], total_round, byte_units[byte_tu],
+ bps, bps_units[bps_u]);
- print_progress_bar(percent, suffix);
+ print_progress_bar(percent, suffix);
}
void sscp_monitor_thread_cleanup(void *arg)
{
- struct sscp *sscp = arg;
- struct timeval end;
- struct file *f;
- size_t total, done;
- int n;
+ struct sscp *sscp = arg;
+ struct timeval end;
+ struct file *f;
+ size_t total, done;
+ int n;
- total = done = 0;
+ total = done = 0;
- gettimeofday(&end, NULL);
+ gettimeofday(&end, NULL);
- /* get total byte to be transferred */
- list_for_each_entry(f, &sscp->file_list, list) {
- total += f->size;
- }
+ /* get total byte to be transferred */
+ list_for_each_entry(f, &sscp->file_list, list) {
+ total += f->size;
+ }
- /* get total byte transferred */
- for (n = 0; n < nr_threads; n++) {
- done += threads[n].done;
- }
+ /* get total byte transferred */
+ for (n = 0; n < nr_threads; n++) {
+ done += threads[n].done;
+ }
- print_progress(&sscp->start, &end, total, 0, done);
- fputs("\n", stdout); /* the final ouput. we need \n */
+ print_progress(&sscp->start, &end, total, 0, done);
+ fputs("\n", stdout); /* the final ouput. we need \n */
}
void *sscp_monitor_thread(void *arg)
{
- struct sscp *sscp = arg;
- struct timeval a, b;
- struct file *f;
- bool all_done;
- size_t total, done, last;
- int n;
-
- pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
- pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
- pthread_cleanup_push(sscp_monitor_thread_cleanup, sscp);
-
- /* get total byte to be transferred */
- total = 0;
- list_for_each_entry(f, &sscp->file_list, list) {
- total += f->size;
- }
-
- while (1) {
- all_done = true;
- last = done = 0;
-
- for (n = 0; n < nr_threads; n++) {
- last += threads[n].done;
- }
- gettimeofday(&b, NULL);
-
- usleep(500000);
-
- for (n = 0; n < nr_threads; n++) {
- done += threads[n].done;;
- if (!threads[n].finished)
- all_done = false;
- }
- gettimeofday(&a, NULL);
-
- print_progress(&b, &a, total, last, done);
-
- if (all_done || total == done)
- break;
- }
-
- pthread_cleanup_pop(1);
-
- return NULL;
+ struct sscp *sscp = arg;
+ struct timeval a, b;
+ struct file *f;
+ bool all_done;
+ size_t total, done, last;
+ int n;
+
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+ pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
+ pthread_cleanup_push(sscp_monitor_thread_cleanup, sscp);
+
+ /* get total byte to be transferred */
+ total = 0;
+ list_for_each_entry(f, &sscp->file_list, list) {
+ total += f->size;
+ }
+
+ while (1) {
+ all_done = true;
+ last = done = 0;
+
+ for (n = 0; n < nr_threads; n++) {
+ last += threads[n].done;
+ }
+ gettimeofday(&b, NULL);
+
+ usleep(500000);
+
+ for (n = 0; n < nr_threads; n++) {
+ done += threads[n].done;;
+ if (!threads[n].finished)
+ all_done = false;
+ }
+ gettimeofday(&a, NULL);
+
+ print_progress(&b, &a, total, last, done);
+
+ if (all_done || total == done)
+ break;
+ }
+
+ pthread_cleanup_pop(1);
+
+ return NULL;
}
diff --git a/src/platform.c b/src/platform.c
index 1a87cd3..ea6b8ad 100644
--- a/src/platform.c
+++ b/src/platform.c
@@ -14,25 +14,25 @@
#ifdef __APPLE__
int nr_cpus()
{
- int n;
- size_t size = sizeof(n);
+ int n;
+ size_t size = sizeof(n);
- if (sysctlbyname("machdep.cpu.core_count", &n, &size, NULL, 0) != 0) {
- pr_err("failed to get number of cpu cores: %s\n", strerrno());
- return -1;
- }
+ if (sysctlbyname("machdep.cpu.core_count", &n, &size, NULL, 0) != 0) {
+ pr_err("failed to get number of cpu cores: %s\n", strerrno());
+ return -1;
+ }
- return n;
+ return n;
}
#endif
#ifdef linux
int nr_cpus()
{
- cpu_set_t cpu_set;
- if (sched_getaffinity(0, sizeof(cpu_set_t), &cpu_set) == 0)
- return CPU_COUNT(&cpu_set);
- return -1;
+ cpu_set_t cpu_set;
+ if (sched_getaffinity(0, sizeof(cpu_set_t), &cpu_set) == 0)
+ return CPU_COUNT(&cpu_set);
+ return -1;
}
#endif
diff --git a/src/pprint.c b/src/pprint.c
index 51eb4ad..64f8a21 100644
--- a/src/pprint.c
+++ b/src/pprint.c
@@ -13,20 +13,20 @@ static pthread_mutex_t pprint_lock = PTHREAD_MUTEX_INITIALIZER;
void pprint_set_level(int level)
{
- pprint_level = level;
+ pprint_level = level;
}
void pprint(int level, const char *fmt, ...)
{
- va_list va;
+ va_list va;
- if (level <= pprint_level) {
- pthread_mutex_lock(&pprint_lock);
- va_start(va, fmt);
- vfprintf(stdout, fmt, va);
- fflush(stdout);
- va_end(va);
- pthread_mutex_unlock(&pprint_lock);
- }
+ if (level <= pprint_level) {
+ pthread_mutex_lock(&pprint_lock);
+ va_start(va, fmt);
+ vfprintf(stdout, fmt, va);
+ fflush(stdout);
+ va_end(va);
+ pthread_mutex_unlock(&pprint_lock);
+ }
}
diff --git a/src/ssh.c b/src/ssh.c
index b64e0a9..65d6e0c 100644
--- a/src/ssh.c
+++ b/src/ssh.c
@@ -10,265 +10,265 @@ static int ssh_verify_known_hosts(ssh_session session);
static int ssh_set_opts(ssh_session ssh, struct ssh_opts *opts)
{
- ssh_set_log_level(opts->debuglevel);
-
- if (opts->login_name &&
- ssh_options_set(ssh, SSH_OPTIONS_USER, opts->login_name) < 0) {
- pr_err("failed to set login name\n");
- return -1;
- }
-
- if (opts->port &&
- ssh_options_set(ssh, SSH_OPTIONS_PORT_STR, opts->port) < 0) {
- pr_err("failed to set port number\n");
- return -1;
- }
-
- if (opts->identity &&
- ssh_options_set(ssh, SSH_OPTIONS_IDENTITY, opts->identity) < 0) {
- pr_err("failed to set identity\n");
- return -1;
- }
-
- if (opts->cipher) {
- if (ssh_options_set(ssh, SSH_OPTIONS_CIPHERS_C_S, opts->cipher) < 0) {
- pr_err("failed to set cipher client to server\n");
- return -1;
- }
- if (ssh_options_set(ssh, SSH_OPTIONS_CIPHERS_S_C, opts->cipher) < 0) {
- pr_err("failed to set cipher client to server\n");
- return -1;
- }
- }
-
- if (opts->compress &&
- ssh_options_set(ssh, SSH_OPTIONS_COMPRESSION, "yes") < 0) {
- pr_err("failed to enable ssh compression\n");
- return -1;
- }
-
- return 0;
+ ssh_set_log_level(opts->debuglevel);
+
+ if (opts->login_name &&
+ ssh_options_set(ssh, SSH_OPTIONS_USER, opts->login_name) < 0) {
+ pr_err("failed to set login name\n");
+ return -1;
+ }
+
+ if (opts->port &&
+ ssh_options_set(ssh, SSH_OPTIONS_PORT_STR, opts->port) < 0) {
+ pr_err("failed to set port number\n");
+ return -1;
+ }
+
+ if (opts->identity &&
+ ssh_options_set(ssh, SSH_OPTIONS_IDENTITY, opts->identity) < 0) {
+ pr_err("failed to set identity\n");
+ return -1;
+ }
+
+ if (opts->cipher) {
+ if (ssh_options_set(ssh, SSH_OPTIONS_CIPHERS_C_S, opts->cipher) < 0) {
+ pr_err("failed to set cipher client to server\n");
+ return -1;
+ }
+ if (ssh_options_set(ssh, SSH_OPTIONS_CIPHERS_S_C, opts->cipher) < 0) {
+ pr_err("failed to set cipher client to server\n");
+ return -1;
+ }
+ }
+
+ if (opts->compress &&
+ ssh_options_set(ssh, SSH_OPTIONS_COMPRESSION, "yes") < 0) {
+ pr_err("failed to enable ssh compression\n");
+ return -1;
+ }
+
+ return 0;
}
static int ssh_authenticate(ssh_session ssh, struct ssh_opts *opts)
{
- int auth_bit_mask;
- int ret;
-
- /* none method */
- ret = ssh_userauth_none(ssh, NULL);
- if (ret == SSH_AUTH_SUCCESS)
- return 0;
-
- auth_bit_mask = ssh_userauth_list(ssh, NULL);
-
- if (auth_bit_mask & SSH_AUTH_METHOD_NONE &&
- ssh_userauth_none(ssh, NULL) == SSH_AUTH_SUCCESS) {
- return 0;
- }
-
- if (auth_bit_mask & SSH_AUTH_METHOD_PUBLICKEY &&
- ssh_userauth_publickey_auto(ssh, NULL, NULL) == SSH_AUTH_SUCCESS) {
- return 0;
- }
-
- if (auth_bit_mask & SSH_AUTH_METHOD_PASSWORD) {
- if (!opts->password) {
- opts->password = getpass("Password: ");
- }
- if (ssh_userauth_password(ssh, NULL, opts->password) == SSH_AUTH_SUCCESS)
- return 0;
- }
-
- pr_err("authentication failure: %s\n", ssh_get_error(ssh));
- return -1;
+ int auth_bit_mask;
+ int ret;
+
+/* none method */
+ ret = ssh_userauth_none(ssh, NULL);
+ if (ret == SSH_AUTH_SUCCESS)
+ return 0;
+
+ auth_bit_mask = ssh_userauth_list(ssh, NULL);
+
+ if (auth_bit_mask & SSH_AUTH_METHOD_NONE &&
+ ssh_userauth_none(ssh, NULL) == SSH_AUTH_SUCCESS) {
+ return 0;
+ }
+
+ if (auth_bit_mask & SSH_AUTH_METHOD_PUBLICKEY &&
+ ssh_userauth_publickey_auto(ssh, NULL, NULL) == SSH_AUTH_SUCCESS) {
+ return 0;
+ }
+
+ if (auth_bit_mask & SSH_AUTH_METHOD_PASSWORD) {
+ if (!opts->password) {
+ opts->password = getpass("Password: ");
+ }
+ if (ssh_userauth_password(ssh, NULL, opts->password) == SSH_AUTH_SUCCESS)
+ return 0;
+ }
+
+ pr_err("authentication failure: %s\n", ssh_get_error(ssh));
+ return -1;
}
static ssh_session ssh_make_ssh_session(char *sshdst, struct ssh_opts *opts)
{
- ssh_session ssh = ssh_new();
+ ssh_session ssh = ssh_new();
- if (ssh_set_opts(ssh, opts) != 0)
- goto free_out;
+ if (ssh_set_opts(ssh, opts) != 0)
+ goto free_out;
- if (ssh_options_set(ssh, SSH_OPTIONS_HOST, sshdst) != SSH_OK) {
- pr_err("failed to set destination host\n");
- goto free_out;
- }
+ if (ssh_options_set(ssh, SSH_OPTIONS_HOST, sshdst) != SSH_OK) {
+ pr_err("failed to set destination host\n");
+ goto free_out;
+ }
- if (ssh_connect(ssh) != SSH_OK) {
- pr_err("failed to connect ssh server: %s\n", ssh_get_error(ssh));
- goto free_out;
- }
+ if (ssh_connect(ssh) != SSH_OK) {
+ pr_err("failed to connect ssh server: %s\n", ssh_get_error(ssh));
+ goto free_out;
+ }
- if (ssh_authenticate(ssh, opts) != 0) {
- pr_err("authentication failed: %s\n", ssh_get_error(ssh));
- goto disconnect_out;
- }
+ if (ssh_authenticate(ssh, opts) != 0) {
+ pr_err("authentication failed: %s\n", ssh_get_error(ssh));
+ goto disconnect_out;
+ }
- if (ssh_verify_known_hosts(ssh) != 0) {
- goto disconnect_out;
- }
+ if (ssh_verify_known_hosts(ssh) != 0) {
+ goto disconnect_out;
+ }
- return ssh;
+ return ssh;
disconnect_out:
- ssh_disconnect(ssh);
+ ssh_disconnect(ssh);
free_out:
- ssh_free(ssh);
- return NULL;
+ ssh_free(ssh);
+ return NULL;
}
sftp_session ssh_make_sftp_session(char *sshdst, struct ssh_opts *opts)
{
- sftp_session sftp;
- ssh_session ssh = ssh_make_ssh_session(sshdst, opts);
-
- if (!ssh) {
- return NULL;
- }
-
- sftp = sftp_new(ssh);
- if (!sftp) {
- pr_err("failed to allocate sftp session: %s\n", ssh_get_error(ssh));
- goto err_out;
- }
-
- if (sftp_init(sftp) != SSH_OK) {
- pr_err("failed to initialize sftp session: err code %d\n",
- sftp_get_error(sftp));
- goto err_out;
- }
-
- return sftp;
+ sftp_session sftp;
+ ssh_session ssh = ssh_make_ssh_session(sshdst, opts);
+
+ if (!ssh) {
+ return NULL;
+ }
+
+ sftp = sftp_new(ssh);
+ if (!sftp) {
+ pr_err("failed to allocate sftp session: %s\n", ssh_get_error(ssh));
+ goto err_out;
+ }
+
+ if (sftp_init(sftp) != SSH_OK) {
+ pr_err("failed to initialize sftp session: err code %d\n",
+ sftp_get_error(sftp));
+ goto err_out;
+ }
+
+ return sftp;
err_out:
- ssh_disconnect(ssh);
- ssh_free(ssh);
- return NULL;
+ ssh_disconnect(ssh);
+ ssh_free(ssh);
+ return NULL;
}
/* copied from https://api.libssh.org/stable/libssh_tutor_guided_tour.html*/
static int ssh_verify_known_hosts(ssh_session session)
{
- enum ssh_known_hosts_e state;
- unsigned char *hash = NULL;
- ssh_key srv_pubkey = NULL;
- size_t hlen;
- char buf[10];
- char *hexa;
- char *p;
- int cmp;
- int rc;
-
- rc = ssh_get_server_publickey(session, &srv_pubkey);
- if (rc < 0) {
- return -1;
- }
-
- rc = ssh_get_publickey_hash(srv_pubkey,
- SSH_PUBLICKEY_HASH_SHA1,
- &hash,
- &hlen);
- ssh_key_free(srv_pubkey);
- if (rc < 0) {
- return -1;
- }
-
- state = ssh_session_is_known_server(session);
- switch (state) {
- case SSH_KNOWN_HOSTS_OK:
- /* OK */
-
- break;
- case SSH_KNOWN_HOSTS_CHANGED:
- fprintf(stderr, "Host key for server changed: it is now:\n");
- //ssh_print_hexa("Public key hash", hash, hlen);
- fprintf(stderr, "For security reasons, connection will be stopped\n");
- ssh_clean_pubkey_hash(&hash);
-
- return -1;
- case SSH_KNOWN_HOSTS_OTHER:
- fprintf(stderr, "The host key for this server was not found but an other"
- "type of key exists.\n");
- fprintf(stderr, "An attacker might change the default server key to"
- "confuse your client into thinking the key does not exist\n");
- ssh_clean_pubkey_hash(&hash);
-
- return -1;
- case SSH_KNOWN_HOSTS_NOT_FOUND:
- fprintf(stderr, "Could not find known host file.\n");
- fprintf(stderr, "If you accept the host key here, the file will be"
- "automatically created.\n");
-
- /* FALL THROUGH to SSH_SERVER_NOT_KNOWN behavior */
-
- case SSH_KNOWN_HOSTS_UNKNOWN:
- hexa = ssh_get_hexa(hash, hlen);
- fprintf(stderr,"The server is unknown. Do you trust the host key?\n");
- fprintf(stderr, "Public key hash: %s\n", hexa);
- ssh_string_free_char(hexa);
- ssh_clean_pubkey_hash(&hash);
- p = fgets(buf, sizeof(buf), stdin);
- if (p == NULL) {
- return -1;
- }
-
- cmp = strncasecmp(buf, "yes", 3);
- if (cmp != 0) {
- return -1;
- }
-
- rc = ssh_session_update_known_hosts(session);
- if (rc < 0) {
- fprintf(stderr, "Error %s\n", strerror(errno));
- return -1;
- }
-
- break;
- case SSH_KNOWN_HOSTS_ERROR:
- fprintf(stderr, "Error %s", ssh_get_error(session));
- ssh_clean_pubkey_hash(&hash);
- return -1;
- }
-
- ssh_clean_pubkey_hash(&hash);
- return 0;
+ enum ssh_known_hosts_e state;
+ unsigned char *hash = NULL;
+ ssh_key srv_pubkey = NULL;
+ size_t hlen;
+ char buf[10];
+ char *hexa;
+ char *p;
+ int cmp;
+ int rc;
+
+ rc = ssh_get_server_publickey(session, &srv_pubkey);
+ if (rc < 0) {
+ return -1;
+ }
+
+ rc = ssh_get_publickey_hash(srv_pubkey,
+ SSH_PUBLICKEY_HASH_SHA1,
+ &hash,
+ &hlen);
+ ssh_key_free(srv_pubkey);
+ if (rc < 0) {
+ return -1;
+ }
+
+ state = ssh_session_is_known_server(session);
+ switch (state) {
+ case SSH_KNOWN_HOSTS_OK:
+/* OK */
+
+ break;
+ case SSH_KNOWN_HOSTS_CHANGED:
+ fprintf(stderr, "Host key for server changed: it is now:\n");
+//ssh_print_hexa("Public key hash", hash, hlen);
+ fprintf(stderr, "For security reasons, connection will be stopped\n");
+ ssh_clean_pubkey_hash(&hash);
+
+ return -1;
+ case SSH_KNOWN_HOSTS_OTHER:
+ fprintf(stderr, "The host key for this server was not found but an other"
+ "type of key exists.\n");
+ fprintf(stderr, "An attacker might change the default server key to"
+ "confuse your client into thinking the key does not exist\n");
+ ssh_clean_pubkey_hash(&hash);
+
+ return -1;
+ case SSH_KNOWN_HOSTS_NOT_FOUND:
+ fprintf(stderr, "Could not find known host file.\n");
+ fprintf(stderr, "If you accept the host key here, the file will be"
+ "automatically created.\n");
+
+/* FALL THROUGH to SSH_SERVER_NOT_KNOWN behavior */
+
+ case SSH_KNOWN_HOSTS_UNKNOWN:
+ hexa = ssh_get_hexa(hash, hlen);
+ fprintf(stderr,"The server is unknown. Do you trust the host key?\n");
+ fprintf(stderr, "Public key hash: %s\n", hexa);
+ ssh_string_free_char(hexa);
+ ssh_clean_pubkey_hash(&hash);
+ p = fgets(buf, sizeof(buf), stdin);
+ if (p == NULL) {
+ return -1;
+ }
+
+ cmp = strncasecmp(buf, "yes", 3);
+ if (cmp != 0) {
+ return -1;
+ }
+
+ rc = ssh_session_update_known_hosts(session);
+ if (rc < 0) {
+ fprintf(stderr, "Error %s\n", strerror(errno));
+ return -1;
+ }
+
+ break;
+ case SSH_KNOWN_HOSTS_ERROR:
+ fprintf(stderr, "Error %s", ssh_get_error(session));
+ ssh_clean_pubkey_hash(&hash);
+ return -1;
+ }
+
+ ssh_clean_pubkey_hash(&hash);
+ return 0;
}
void ssh_sftp_close(sftp_session sftp)
{
- ssh_session ssh = sftp_ssh(sftp);
- sftp_free(sftp);
- ssh_disconnect(ssh);
- ssh_free(ssh);
+ ssh_session ssh = sftp_ssh(sftp);
+ sftp_free(sftp);
+ ssh_disconnect(ssh);
+ ssh_free(ssh);
}
int sftp_write2(sftp_file sf, const void *buf, size_t len, size_t sftp_buf_sz)
{
- int ret, nbytes;
-
- for (nbytes = 0; nbytes < len;) {
- ret = sftp_write(sf, buf + nbytes,
- min(len - nbytes, sftp_buf_sz));
- if (ret < 0)
- return ret;
- nbytes += ret;
- }
- return nbytes;
+ int ret, nbytes;
+
+ for (nbytes = 0; nbytes < len;) {
+ ret = sftp_write(sf, buf + nbytes,
+ min(len - nbytes, sftp_buf_sz));
+ if (ret < 0)
+ return ret;
+ nbytes += ret;
+ }
+ return nbytes;
}
int sftp_read2(sftp_file sf, void *buf, size_t len, size_t sftp_buf_sz)
{
- int ret, nbytes;
-
- for (nbytes = 0; nbytes < len;) {
- ret = sftp_read(sf, buf + nbytes,
- min(len - nbytes, sftp_buf_sz));
- if (ret < 0)
- return ret;
- nbytes += ret;
- }
- return nbytes;
+ int ret, nbytes;
+
+ for (nbytes = 0; nbytes < len;) {
+ ret = sftp_read(sf, buf + nbytes,
+ min(len - nbytes, sftp_buf_sz));
+ if (ret < 0)
+ return ret;
+ nbytes += ret;
+ }
+ return nbytes;
}
diff --git a/src/ssh.h b/src/ssh.h
index 84e3d9e..2dd99f5 100644
--- a/src/ssh.h
+++ b/src/ssh.h
@@ -6,14 +6,14 @@
struct ssh_opts {
- char *login_name; /* -l */
- char *port; /* -p */
- char *identity; /* -i */
- char *cipher; /* -c */
- int compress; /* -C */
- int debuglevel; /* -v */
-
- char *password; /* filled at the first connecting phase */
+ char *login_name; /* -l */
+ char *port; /* -p */
+ char *identity; /* -i */
+ char *cipher; /* -c */
+ int compress; /* -C */
+ int debuglevel; /* -v */
+
+ char *password; /* filled at the first connecting phase */
};
/* ssh_make_sftp_session() creates sftp_session. sshdst accpets
diff --git a/src/util.h b/src/util.h
index cf4bee8..774e80a 100644
--- a/src/util.h
+++ b/src/util.h
@@ -12,7 +12,7 @@
#define pr(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
#define pr_info(fmt, ...) fprintf(stderr, "INFO:%s(): " fmt, \
- __func__, ##__VA_ARGS__)
+ __func__, ##__VA_ARGS__)
#define pr_warn(fmt, ...) fprintf(stderr, "\x1b[1m\x1b[33m" \
"WARN:%s():\x1b[0m " fmt, \
@@ -24,8 +24,8 @@
#ifdef DEBUG
#define pr_debug(fmt, ...) fprintf(stderr, "\x1b[1m\x1b[33m" \
- "DEBUG:%s():\x1b[0m " fmt, \
- __func__, ##__VA_ARGS__);
+ "DEBUG:%s():\x1b[0m " fmt, \
+ __func__, ##__VA_ARGS__);
#else
#define pr_debug(fmt, ...)
#endif