1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <util.h>
#include <ssh.h>
#include <file.h>
#include <platform.h>
#define DEFAULT_MIN_CHUNK_SZ (2 << 20) /* 2MB */
void usage(bool print_help) {
printf("sscp: super scp, copy files over multiple ssh connections\n"
"\n"
"Usage: sscp [rvC] [-n max_conns] [-s min_chunk_sz] [-S max_chunk_sz]\n"
" [-l login_name] [-p port] [-i identity_file]\n"
" [-c cipher_spec] source ... target\n"
"\n");
if (!print_help)
return;
printf(" -r copy directory recusrively\n"
" -n NR_CONNECTIONS max number of connections (default: # of cpu cores)\n"
" -s CHUNKSIZE min chunk size (default: 2MB)\n"
" -S CHUNKSIZE max chunk size (default: filesize / nr_conn)\n"
"\n"
" -l LOGIN_NAME login name\n"
" -p PORT port number\n"
" -i IDENTITY identity to be used for ssh\n"
" -c CIPHER cipher spec, see `ssh -Q cipher`\n"
" -C enable compression on libssh\n"
" -v increment output level\n"
" -h print this help\n"
"\n");
}
int main(int argc, char **argv)
{
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;
char ch;
memset(&opts, 0, sizeof(opts));
while ((ch = getopt(argc, argv, "r: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) {
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 'l':
opts.login_name = optarg;
break;
case 'p':
opts.port = optarg;
break;
case 'i':
opts.identity = optarg;
break;
case 'c':
opts.cipher = optarg;
break;
case 'C':
opts.compress++;
break;
case 'v':
opts.debuglevel++;
break;
case 'h':
usage(true);
return 1;
default:
usage(false);
return 1;
}
}
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;
}
printf("opts.port %s\n", opts.port);
int n;
for (n = 0; n < argc; n++) {
printf("%d %s\n", n, argv[n]);
}
printf("optind %d", optind);
return 0;
}
|