diff options
Diffstat (limited to 'src/main.c')
-rw-r--r-- | src/main.c | 109 |
1 files changed, 97 insertions, 12 deletions
@@ -3,14 +3,25 @@ #include <stdbool.h> #include <unistd.h> +#include <list.h> #include <util.h> #include <ssh.h> #include <file.h> #include <platform.h> +int verbose = 0; /* util.h */ #define DEFAULT_MIN_CHUNK_SZ (64 << 20) /* 64MB */ +struct sscp { + char *host; /* remote host (and username) */ + sftp_session ctrl; /* control sftp session */ + + struct list_head file_list; + char *target; + bool target_is_remote; +}; + void usage(bool print_help) { printf("sscp: super scp, copy files over multiple ssh connections\n" "\n" @@ -22,8 +33,7 @@ void usage(bool print_help) { if (!print_help) return; - printf(" -r expand directory recusrively\n" - " -n NR_CONNECTIONS max number of connections (default: # of cpu cores)\n" + 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" "\n" @@ -43,22 +53,65 @@ void usage(bool print_help) { "\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]; + +err_out: + for (n = 0; n < cnt; n++) { + free(hostnames[n]); + } + return NULL; +} + int main(int argc, char **argv) { + struct sscp sscp; struct ssh_opts opts; int nr_conn = nr_cpus(); - bool recursive = false; int min_chunk_sz = DEFAULT_MIN_CHUNK_SZ; int max_chunk_sz = 0; + int ret = 0; char ch; memset(&opts, 0, sizeof(opts)); + memset(&sscp, 0, sizeof(sscp)); + INIT_LIST_HEAD(&sscp.file_list); - while ((ch = getopt(argc, argv, "r:n:s:S:l:p:i:c:Cvh")) != -1) { + while ((ch = getopt(argc, argv, "n:s:S:l:p:i:c:Cvh")) != -1) { switch (ch) { - case 'r': - recursive = true; - break; case 'n': nr_conn = atoi(optarg); if (nr_conn < 1) { @@ -113,6 +166,7 @@ int main(int argc, char **argv) break; case 'v': opts.debuglevel++; + verbose++; break; case 'h': usage(true); @@ -129,13 +183,44 @@ int main(int argc, char **argv) return 1; } - printf("opts.port %s\n", opts.port); + if (argc - optind < 2) { + /* sscp needs at lease 2 (src and target) argument */ + usage(false); + return 1; + } + + sscp.target = argv[argc - 1]; + sscp.target_is_remote = file_has_hostname(sscp.target); + + /* create control session */ + sscp.host = find_hostname(optind, argc, argv); + if (!sscp.host) { + pr_err("no remote host given\n"); + return 1; + } + sscp.ctrl = ssh_make_sftp_session(sscp.host, &opts); + if (!sscp.ctrl) + return 1; + + /* check target is directory */ + ret = file_is_directory(sscp.target, sscp.target_is_remote ? sscp.ctrl : NULL); + if (ret < 0) + return 1; + if (ret == 0) { + pr_err("target must be directory\n"); + return 1; + } - int n; - for (n = 0; n < argc; n++) { - printf("%d %s\n", n, argv[n]); + ret = file_fill(sscp.ctrl, &sscp.file_list, &argv[optind], argc - optind - 1); + if (ret < 0) { + ssh_sftp_close(sscp.ctrl); + return 1; } - printf("optind %d", optind); +#ifdef DEBUG + file_dump(&sscp.file_list); +#endif + + ssh_sftp_close(sscp.ctrl); return 0; } |