implement fill_file

This commit is contained in:
Ryo Nakamura
2022-10-16 22:12:03 +09:00
parent 579629dea2
commit def9cfeba7
8 changed files with 929 additions and 32 deletions

View File

@@ -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);
int n;
for (n = 0; n < argc; n++) {
printf("%d %s\n", n, argv[n]);
if (argc - optind < 2) {
/* sscp needs at lease 2 (src and target) argument */
usage(false);
return 1;
}
printf("optind %d", optind);
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;
}
ret = file_fill(sscp.ctrl, &sscp.file_list, &argv[optind], argc - optind - 1);
if (ret < 0) {
ssh_sftp_close(sscp.ctrl);
return 1;
}
#ifdef DEBUG
file_dump(&sscp.file_list);
#endif
ssh_sftp_close(sscp.ctrl);
return 0;
}