mirror of
https://github.com/upa/mscp.git
synced 2026-02-10 14:54:43 +08:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aba14b3fdc | ||
|
|
cd6136399e | ||
|
|
dfdf683828 | ||
|
|
979f110097 | ||
|
|
fe3c4e0a53 | ||
|
|
7b5a97092a | ||
|
|
1313853d7d | ||
|
|
e621035002 | ||
|
|
ef8994d21e | ||
|
|
81d46a1cd1 | ||
|
|
07366397a8 | ||
|
|
f12d10a988 | ||
|
|
afe2182456 | ||
|
|
c4d8e64fab | ||
|
|
049600a39f | ||
|
|
fa15e9093d | ||
|
|
5bca31b75d | ||
|
|
f65cedb4de | ||
|
|
8bad10e42b | ||
|
|
8de47933bf | ||
|
|
440f25b3a5 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,5 +3,6 @@ html
|
|||||||
compile_commands.json
|
compile_commands.json
|
||||||
CMakeUserPresets.json
|
CMakeUserPresets.json
|
||||||
.*.swp
|
.*.swp
|
||||||
|
.cache
|
||||||
|
|
||||||
include/mscp_version.h
|
include/mscp_version.h
|
||||||
|
|||||||
10
debian/changelog
vendored
10
debian/changelog
vendored
@@ -1,4 +1,12 @@
|
|||||||
mscp (0.2.3) UNRELEASED; urgency=medium
|
mscp (0.2.4) UNRELEASED; urgency=medium
|
||||||
|
|
||||||
|
* fix password auth does not work (issue #36)
|
||||||
|
* add Debian and Devuan to the install dep script (pr #38)
|
||||||
|
* fallback to default terminal size on no tty (pr #39)
|
||||||
|
|
||||||
|
-- Ryo Nakamura <upa@haeena.net> Sat, 08 Nov 2025 19:23:07 +0900
|
||||||
|
|
||||||
|
mscp (0.2.3) unstable; urgency=medium
|
||||||
|
|
||||||
* bump libssh version to 0.11.2 (#25)
|
* bump libssh version to 0.11.2 (#25)
|
||||||
* adopt new AIO read API of libssh
|
* adopt new AIO read API of libssh
|
||||||
|
|||||||
@@ -41,6 +41,9 @@ mscp \- copy files over multiple SSH connections
|
|||||||
.BI \-L \ LIMIT_BITRATE\c
|
.BI \-L \ LIMIT_BITRATE\c
|
||||||
]
|
]
|
||||||
[\c
|
[\c
|
||||||
|
.BI \-B \ BIND_ADDR\c
|
||||||
|
]
|
||||||
|
[\c
|
||||||
.BI \-l \ LOGIN_NAME\c
|
.BI \-l \ LOGIN_NAME\c
|
||||||
]
|
]
|
||||||
[\c
|
[\c
|
||||||
@@ -220,6 +223,13 @@ delivered over SSH. Changing this value is not recommended at present.
|
|||||||
Limits the bitrate, specified with k (K), m (M), and g (G), e.g., 100m
|
Limits the bitrate, specified with k (K), m (M), and g (G), e.g., 100m
|
||||||
indicates 100 Mbps.
|
indicates 100 Mbps.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B \-B \fIBIND_ADDR\fR
|
||||||
|
Specifies a local IP address to bind. When multiple -B options are
|
||||||
|
specified, SSH connections will be bound to the addresses in a round
|
||||||
|
robin manner. This feature enables using multiple network interfaces
|
||||||
|
having differnt IP addresses.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-4
|
.B \-4
|
||||||
Uses IPv4 addresses only.
|
Uses IPv4 addresses only.
|
||||||
@@ -435,6 +445,18 @@ will be faster than the default chacha20-poly1305 cipher, particularly
|
|||||||
on hosts that support AES-NI.
|
on hosts that support AES-NI.
|
||||||
|
|
||||||
|
|
||||||
|
.PP
|
||||||
|
Use multiple network interfaces having different IP addresses:
|
||||||
|
|
||||||
|
.nf
|
||||||
|
$ mscp -n 9 -B 10.0.0.10 -B 10.0.0.11 -B 10.0.0.12 many-large-files 192.168.0.1:dst/
|
||||||
|
.fi
|
||||||
|
|
||||||
|
Out of the 9 SSH connections, three of them are bound to each of
|
||||||
|
10.0.0.10, 10.0.0.11, and 10.0.0.12 in a round robin manner.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
.BR scp (1),
|
.BR scp (1),
|
||||||
.BR ssh (1),
|
.BR ssh (1),
|
||||||
|
|||||||
26
doc/mscp.rst
26
doc/mscp.rst
@@ -2,7 +2,7 @@
|
|||||||
MSCP
|
MSCP
|
||||||
====
|
====
|
||||||
|
|
||||||
:Date: v0.2.1
|
:Date: v0.2.4-6-gcd61363
|
||||||
|
|
||||||
NAME
|
NAME
|
||||||
====
|
====
|
||||||
@@ -16,10 +16,11 @@ SYNOPSIS
|
|||||||
*COREMASK* ] [ **-u** *MAX_STARTUPS* ] [ **-I** *INTERVAL* ] [ **-W**
|
*COREMASK* ] [ **-u** *MAX_STARTUPS* ] [ **-I** *INTERVAL* ] [ **-W**
|
||||||
*CHECKPOINT* ] [ **-R** *CHECKPOINT* ] [ **-s** *MIN_CHUNK_SIZE* ] [
|
*CHECKPOINT* ] [ **-R** *CHECKPOINT* ] [ **-s** *MIN_CHUNK_SIZE* ] [
|
||||||
**-S** *MAX_CHUNK_SIZE* ] [ **-a** *NR_AHEAD* ] [ **-b** *BUF_SIZE* ] [
|
**-S** *MAX_CHUNK_SIZE* ] [ **-a** *NR_AHEAD* ] [ **-b** *BUF_SIZE* ] [
|
||||||
**-L** *LIMIT_BITRATE* ] [ **-l** *LOGIN_NAME* ] [ **-P** *PORT* ] [
|
**-L** *LIMIT_BITRATE* ] [ **-B** *BIND_ADDR* ] [ **-l** *LOGIN_NAME* ]
|
||||||
**-F** *SSH_CONFIG* ] [ **-o** *SSH_OPTION* ] [ **-i** *IDENTITY* ] [
|
[ **-P** *PORT* ] [ **-F** *SSH_CONFIG* ] [ **-o** *SSH_OPTION* ] [
|
||||||
**-J** *DESTINATION* ] [ **-c** *CIPHER* ] [ **-M** *HMAC* ] [ **-C**
|
**-i** *IDENTITY* ] [ **-J** *DESTINATION* ] [ **-c** *CIPHER* ] [
|
||||||
*COMPRESS* ] [ **-g** *CONGESTION* ] *source ... target*
|
**-M** *HMAC* ] [ **-C** *COMPRESS* ] [ **-g** *CONGESTION* ] *source
|
||||||
|
... target*
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
===========
|
===========
|
||||||
@@ -120,6 +121,12 @@ OPTIONS
|
|||||||
Limits the bitrate, specified with k (K), m (M), and g (G), e.g.,
|
Limits the bitrate, specified with k (K), m (M), and g (G), e.g.,
|
||||||
100m indicates 100 Mbps.
|
100m indicates 100 Mbps.
|
||||||
|
|
||||||
|
**-B BIND_ADDR**
|
||||||
|
Specifies a local IP address to bind. When multiple -B options are
|
||||||
|
specified, SSH connections will be bound to the addresses in a round
|
||||||
|
robin manner. This feature enables using multiple network interfaces
|
||||||
|
having differnt IP addresses.
|
||||||
|
|
||||||
**-4**
|
**-4**
|
||||||
Uses IPv4 addresses only.
|
Uses IPv4 addresses only.
|
||||||
|
|
||||||
@@ -269,6 +276,15 @@ SFTP WRITE/READ commands, and **-c aes128-gcm@openssh.com** will be
|
|||||||
faster than the default chacha20-poly1305 cipher, particularly on hosts
|
faster than the default chacha20-poly1305 cipher, particularly on hosts
|
||||||
that support AES-NI.
|
that support AES-NI.
|
||||||
|
|
||||||
|
Use multiple network interfaces having different IP addresses:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
$ mscp -n 9 -B 10.0.0.10 -B 10.0.0.11 -B 10.0.0.12 many-large-files 192.168.0.1:dst/
|
||||||
|
|
||||||
|
Out of the 9 SSH connections, three of them are bound to each of
|
||||||
|
10.0.0.10, 10.0.0.11, and 10.0.0.12 in a round robin manner.
|
||||||
|
|
||||||
SEE ALSO
|
SEE ALSO
|
||||||
========
|
========
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,8 @@
|
|||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
#define MSCP_DIRECTION_L2R 1 /** Indicates local to remote copy */
|
#define MSCP_DIRECTION_L2R 1 /** Indicates local to remote copy */
|
||||||
#define MSCP_DIRECTION_R2L 2 /** Indicates remote to local copy */
|
#define MSCP_DIRECTION_R2L 2 /** Indicates remote to local copy */
|
||||||
@@ -59,6 +61,7 @@ struct mscp_ssh_opts {
|
|||||||
/* ssh options */
|
/* ssh options */
|
||||||
char *login_name; /** ssh username */
|
char *login_name; /** ssh username */
|
||||||
char *port; /** ssh port */
|
char *port; /** ssh port */
|
||||||
|
char **bind_addrs; /** addresses to bind, terminated by NULL */
|
||||||
int ai_family; /** address family */
|
int ai_family; /** address family */
|
||||||
char *config; /** path to ssh_config, default ~/.ssh/config*/
|
char *config; /** path to ssh_config, default ~/.ssh/config*/
|
||||||
char **options; /** array of ssh_config options, terminated by NULL */
|
char **options; /** array of ssh_config options, terminated by NULL */
|
||||||
|
|||||||
@@ -38,6 +38,9 @@ make -C build install DESTDIR=%{buildroot}
|
|||||||
|
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Sat Nov 08 2025 Ryo Nakamura <upa@haeena.net> - 0.2.4-1
|
||||||
|
- RPM release for v0.2.4
|
||||||
|
|
||||||
* Tue Aug 12 2025 Ryo Nakamura <upa@haeena.net> - 0.2.3-1
|
* Tue Aug 12 2025 Ryo Nakamura <upa@haeena.net> - 0.2.3-1
|
||||||
- RPM release for v0.2.3
|
- RPM release for v0.2.3
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ case $platform in
|
|||||||
cmd="brew install"
|
cmd="brew install"
|
||||||
pkgs="openssl@3"
|
pkgs="openssl@3"
|
||||||
;;
|
;;
|
||||||
Linux-ubuntu*)
|
Linux-ubuntu* | Linux-debian* | Linux-devuan*)
|
||||||
cmd="apt-get install --no-install-recommends -y"
|
cmd="apt-get install --no-install-recommends -y"
|
||||||
pkgs="gcc make cmake zlib1g-dev libssl-dev libkrb5-dev"
|
pkgs="gcc make cmake zlib1g-dev libssl-dev libkrb5-dev"
|
||||||
;;
|
;;
|
||||||
|
|||||||
@@ -50,8 +50,6 @@ int bwlimit_init(struct bwlimit *bw, uint64_t bps, uint64_t win)
|
|||||||
#define timespeccmp(a, b, expr) \
|
#define timespeccmp(a, b, expr) \
|
||||||
((a.tv_sec * 1000000000 + a.tv_nsec) expr(b.tv_sec * 1000000000 + b.tv_nsec))
|
((a.tv_sec * 1000000000 + a.tv_nsec) expr(b.tv_sec * 1000000000 + b.tv_nsec))
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
int bwlimit_wait(struct bwlimit *bw, size_t nr_bytes)
|
int bwlimit_wait(struct bwlimit *bw, size_t nr_bytes)
|
||||||
{
|
{
|
||||||
struct timespec now, end, rq, rm;
|
struct timespec now, end, rq, rm;
|
||||||
|
|||||||
@@ -9,10 +9,10 @@
|
|||||||
#include <semaphore.h>
|
#include <semaphore.h>
|
||||||
|
|
||||||
struct bwlimit {
|
struct bwlimit {
|
||||||
sem_t *sem; /* semaphore */
|
sem_t *sem; /* semaphore */
|
||||||
uint64_t bps; /* limit bit-rate (bps) */
|
size_t bps; /* limit bit-rate (bps) */
|
||||||
uint64_t win; /* window size (msec) */
|
size_t win; /* window size (msec) */
|
||||||
size_t amt; /* amount of bytes can be sent in a window */
|
size_t amt; /* amount of bytes can be sent in a window */
|
||||||
|
|
||||||
ssize_t credit; /* remaining bytes can be sent in a window */
|
ssize_t credit; /* remaining bytes can be sent in a window */
|
||||||
struct timespec wstart, wend; /* window start time and end time */
|
struct timespec wstart, wend; /* window start time and end time */
|
||||||
|
|||||||
@@ -101,7 +101,6 @@ MDIR *mscp_opendir_wrapped(const char *path)
|
|||||||
|
|
||||||
void mscp_closedir(MDIR *md)
|
void mscp_closedir(MDIR *md)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
if (md->remote)
|
if (md->remote)
|
||||||
sftp_closedir(md->remote);
|
sftp_closedir(md->remote);
|
||||||
else
|
else
|
||||||
|
|||||||
39
src/main.c
39
src/main.c
@@ -28,7 +28,7 @@ void usage(bool print_help)
|
|||||||
"Usage: mscp [-46vqDpdNh] [-n nr_conns] [-m coremask] [-u max_startups]\n"
|
"Usage: mscp [-46vqDpdNh] [-n nr_conns] [-m coremask] [-u max_startups]\n"
|
||||||
" [-I interval] [-W checkpoint] [-R checkpoint]\n"
|
" [-I interval] [-W checkpoint] [-R checkpoint]\n"
|
||||||
" [-s min_chunk_sz] [-S max_chunk_sz] [-a nr_ahead]\n"
|
" [-s min_chunk_sz] [-S max_chunk_sz] [-a nr_ahead]\n"
|
||||||
" [-b buf_sz] [-L limit_bitrate]\n"
|
" [-b buf_sz] [-L limit_bitrate] [-B bind_addr]\n"
|
||||||
" [-l login_name] [-P port] [-F ssh_config] [-o ssh_option]\n"
|
" [-l login_name] [-P port] [-F ssh_config] [-o ssh_option]\n"
|
||||||
" [-i identity_file] [-J destination] [-c cipher_spec] [-M hmac_spec]\n"
|
" [-i identity_file] [-J destination] [-c cipher_spec] [-M hmac_spec]\n"
|
||||||
" [-C compress] [-g congestion]\n"
|
" [-C compress] [-g congestion]\n"
|
||||||
@@ -51,7 +51,8 @@ void usage(bool print_help)
|
|||||||
" -S MAX_CHUNK_SIZE max chunk size (default: filesize/nr_conn/4)\n"
|
" -S MAX_CHUNK_SIZE max chunk size (default: filesize/nr_conn/4)\n"
|
||||||
" -a NR_AHEAD number of inflight SFTP commands (default: 32)\n"
|
" -a NR_AHEAD number of inflight SFTP commands (default: 32)\n"
|
||||||
" -b BUF_SZ buffer size for i/o and transfer\n"
|
" -b BUF_SZ buffer size for i/o and transfer\n"
|
||||||
" -L LIMIT_BITRATE Limit the bitrate, n[KMG] (default: 0, no limit)\n"
|
" -L LIMIT_BITRATE limit the bitrate, n[KMG] (default: 0, no limit)\n"
|
||||||
|
" -B BIND_ADDR bind address (accept multiple times)\n"
|
||||||
"\n"
|
"\n"
|
||||||
" -4 use IPv4\n"
|
" -4 use IPv4\n"
|
||||||
" -6 use IPv6\n"
|
" -6 use IPv6\n"
|
||||||
@@ -117,8 +118,6 @@ char *split_user_host_path(const char *s, char **userp, char **hostp, char **pat
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
user = NULL;
|
|
||||||
host = NULL;
|
|
||||||
path = tmp;
|
path = tmp;
|
||||||
for (cp = tmp; *cp; cp++) {
|
for (cp = tmp; *cp; cp++) {
|
||||||
if (*cp == '@' && (cp > tmp) && *(cp - 1) != '\\' && user == NULL) {
|
if (*cp == '@' && (cp > tmp) && *(cp - 1) != '\\' && user == NULL) {
|
||||||
@@ -211,7 +210,6 @@ struct target *validate_targets(char **arg, int len)
|
|||||||
pr_err("calloc: %s", strerrno());
|
pr_err("calloc: %s", strerrno());
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
memset(t, 0, len * sizeof(struct target));
|
|
||||||
|
|
||||||
/* split remote:path into remote and path */
|
/* split remote:path into remote and path */
|
||||||
for (n = 0; n < len; n++) {
|
for (n = 0; n < len; n++) {
|
||||||
@@ -309,7 +307,7 @@ long atol_with_unit(char *value, bool i)
|
|||||||
{
|
{
|
||||||
/* value must be "\d+[kKmMgG]?" */
|
/* value must be "\d+[kKmMgG]?" */
|
||||||
|
|
||||||
char *u = value + (strlen(optarg) - 1);
|
char *u = value + (strlen(value) - 1);
|
||||||
long k = i ? 1024 : 1000;
|
long k = i ? 1024 : 1000;
|
||||||
long factor = 1;
|
long factor = 1;
|
||||||
long v;
|
long v;
|
||||||
@@ -359,18 +357,18 @@ int main(int argc, char **argv)
|
|||||||
struct mscp_ssh_opts s;
|
struct mscp_ssh_opts s;
|
||||||
struct mscp_opts o;
|
struct mscp_opts o;
|
||||||
struct target *t;
|
struct target *t;
|
||||||
int pipe_fd[2];
|
|
||||||
int ch, n, i, ret;
|
int ch, n, i, ret;
|
||||||
int direction = 0;
|
int direction = 0;
|
||||||
char *remote = NULL, *checkpoint_save = NULL, *checkpoint_load = NULL;
|
char *remote = NULL, *checkpoint_save = NULL, *checkpoint_load = NULL;
|
||||||
bool quiet = false, dryrun = false, resume = false;
|
bool quiet = false, dryrun = false, resume = false;
|
||||||
|
int nr_baddrs = 0;
|
||||||
int nr_options = 0;
|
int nr_options = 0;
|
||||||
|
|
||||||
memset(&s, 0, sizeof(s));
|
memset(&s, 0, sizeof(s));
|
||||||
memset(&o, 0, sizeof(o));
|
memset(&o, 0, sizeof(o));
|
||||||
o.severity = MSCP_SEVERITY_WARN;
|
o.severity = MSCP_SEVERITY_WARN;
|
||||||
|
|
||||||
#define mscpopts "n:m:u:I:W:R:s:S:a:b:L:46vqDrl:P:F:o:i:J:c:M:C:g:pdNh"
|
#define mscpopts "n:m:u:I:W:R:s:S:a:b:L:B:46vqDrl:P:F:o:i:J:c:M:C:g:pdNh"
|
||||||
while ((ch = getopt(argc, argv, mscpopts)) != -1) {
|
while ((ch = getopt(argc, argv, mscpopts)) != -1) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'n':
|
case 'n':
|
||||||
@@ -411,6 +409,17 @@ int main(int argc, char **argv)
|
|||||||
case 'L':
|
case 'L':
|
||||||
o.bitrate = atol_with_unit(optarg, false);
|
o.bitrate = atol_with_unit(optarg, false);
|
||||||
break;
|
break;
|
||||||
|
case 'B':
|
||||||
|
nr_baddrs++;
|
||||||
|
s.bind_addrs = realloc(s.bind_addrs,
|
||||||
|
sizeof(char *) * (nr_baddrs + 1));
|
||||||
|
if (!s.bind_addrs) {
|
||||||
|
pr_err("realloc: %s", strerrno());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
s.bind_addrs[nr_baddrs - 1] = optarg;
|
||||||
|
s.bind_addrs[nr_baddrs] = NULL;
|
||||||
|
break;
|
||||||
case '4':
|
case '4':
|
||||||
s.ai_family = AF_INET;
|
s.ai_family = AF_INET;
|
||||||
break;
|
break;
|
||||||
@@ -697,8 +706,13 @@ void print_progress_bar(double percent, char *suffix)
|
|||||||
|
|
||||||
buf[0] = '\0';
|
buf[0] = '\0';
|
||||||
|
|
||||||
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) < 0)
|
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) < 0 || ws.ws_col == 0) {
|
||||||
return; /* XXX */
|
|
||||||
|
// fallback to default
|
||||||
|
ws.ws_col = 80;
|
||||||
|
ws.ws_row = 24;
|
||||||
|
}
|
||||||
|
|
||||||
bar_width = min(sizeof(buf), ws.ws_col) - strlen(suffix) - 7;
|
bar_width = min(sizeof(buf), ws.ws_col) - strlen(suffix) - 7;
|
||||||
|
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
@@ -776,8 +790,6 @@ struct xfer_stat x;
|
|||||||
void print_stat(bool final)
|
void print_stat(bool final)
|
||||||
{
|
{
|
||||||
struct mscp_stats s;
|
struct mscp_stats s;
|
||||||
char buf[8192];
|
|
||||||
int timeout;
|
|
||||||
|
|
||||||
gettimeofday(&x.after, NULL);
|
gettimeofday(&x.after, NULL);
|
||||||
if (calculate_timedelta(&x.before, &x.after) > 1 || final) {
|
if (calculate_timedelta(&x.before, &x.after) > 1 || final) {
|
||||||
@@ -793,9 +805,6 @@ void print_stat(bool final)
|
|||||||
|
|
||||||
void *print_stat_thread(void *arg)
|
void *print_stat_thread(void *arg)
|
||||||
{
|
{
|
||||||
struct mscp_stats s;
|
|
||||||
char buf[8192];
|
|
||||||
|
|
||||||
memset(&x, 0, sizeof(x));
|
memset(&x, 0, sizeof(x));
|
||||||
gettimeofday(&x.start, NULL);
|
gettimeofday(&x.start, NULL);
|
||||||
x.before = x.start;
|
x.before = x.start;
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ struct mscp {
|
|||||||
|
|
||||||
static int expand_coremask(const char *coremask, int **cores, int *nr_cores)
|
static int expand_coremask(const char *coremask, int **cores, int *nr_cores)
|
||||||
{
|
{
|
||||||
int n, *core_list, core_list_len = 0, nr_usable, nr_all;
|
int n, *core_list, nr_usable, nr_all;
|
||||||
char c[2] = { 'x', '\0' };
|
char c[2] = { 'x', '\0' };
|
||||||
const char *_coremask;
|
const char *_coremask;
|
||||||
long v, needle;
|
long v, needle;
|
||||||
@@ -273,7 +273,6 @@ struct mscp *mscp_init(struct mscp_opts *o, struct mscp_ssh_opts *s)
|
|||||||
priv_set_errv("bwlimit_init: %s", strerrno());
|
priv_set_errv("bwlimit_init: %s", strerrno());
|
||||||
goto free_out;
|
goto free_out;
|
||||||
}
|
}
|
||||||
pr_notice("bitrate limit: %lu bps", o->bitrate);
|
|
||||||
|
|
||||||
/* workaround: set libssh using openssh proxyjump
|
/* workaround: set libssh using openssh proxyjump
|
||||||
* https://gitlab.com/libssh/libssh-mirror/-/issues/319 */
|
* https://gitlab.com/libssh/libssh-mirror/-/issues/319 */
|
||||||
@@ -563,6 +562,9 @@ int mscp_start(struct mscp *m)
|
|||||||
m->opts->nr_threads = n;
|
m->opts->nr_threads = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pr_notice("threads: %d",m->opts->nr_threads);
|
||||||
|
pr_notice("bwlimit: %ld bps", m->bw.bps);
|
||||||
|
|
||||||
for (n = 0; n < m->opts->nr_threads; n++) {
|
for (n = 0; n < m->opts->nr_threads; n++) {
|
||||||
t = mscp_copy_thread_spawn(m, n);
|
t = mscp_copy_thread_spawn(m, n);
|
||||||
if (!t)
|
if (!t)
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ void set_print_severity(int serverity)
|
|||||||
{
|
{
|
||||||
if (serverity < 0)
|
if (serverity < 0)
|
||||||
__print_severity = -1; /* no print */
|
__print_severity = -1; /* no print */
|
||||||
__print_severity = serverity;
|
else
|
||||||
|
__print_severity = serverity;
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_print_severity()
|
int get_print_severity()
|
||||||
|
|||||||
61
src/ssh.c
61
src/ssh.c
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include <ssh.h>
|
#include <ssh.h>
|
||||||
#include <mscp.h>
|
#include <mscp.h>
|
||||||
|
#include <atomic.h>
|
||||||
#include <strerrno.h>
|
#include <strerrno.h>
|
||||||
|
|
||||||
#include "libssh/callbacks.h"
|
#include "libssh/callbacks.h"
|
||||||
@@ -14,6 +15,9 @@
|
|||||||
static int ssh_verify_known_hosts(ssh_session session);
|
static int ssh_verify_known_hosts(ssh_session session);
|
||||||
static int ssh_authenticate_kbdint(ssh_session session);
|
static int ssh_authenticate_kbdint(ssh_session session);
|
||||||
|
|
||||||
|
static lock bind_addr_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
static int bind_addr_idx;
|
||||||
|
|
||||||
static int ssh_set_opts(ssh_session ssh, struct mscp_ssh_opts *opts)
|
static int ssh_set_opts(ssh_session ssh, struct mscp_ssh_opts *opts)
|
||||||
{
|
{
|
||||||
ssh_set_log_level(opts->debug_level);
|
ssh_set_log_level(opts->debug_level);
|
||||||
@@ -29,6 +33,21 @@ static int ssh_set_opts(ssh_session ssh, struct mscp_ssh_opts *opts)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opts->bind_addrs) {
|
||||||
|
/* ssh_set_opts can be called from multiple threads,
|
||||||
|
* thus protect bind_addr_idx with a lock. */
|
||||||
|
char *bind_addr;
|
||||||
|
LOCK_ACQUIRE(&bind_addr_lock);
|
||||||
|
bind_addr = opts->bind_addrs[bind_addr_idx];
|
||||||
|
bind_addr_idx = (opts->bind_addrs[bind_addr_idx + 1] == NULL ?
|
||||||
|
0 : bind_addr_idx + 1);
|
||||||
|
LOCK_RELEASE();
|
||||||
|
if (ssh_options_set(ssh, SSH_OPTIONS_BINDADDR, bind_addr) < 0) {
|
||||||
|
priv_set_errv("failed to set bind address %s", bind_addr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (opts->ai_family &&
|
if (opts->ai_family &&
|
||||||
ssh_options_set(ssh, SSH_OPTIONS_AI_FAMILY, &opts->ai_family) < 0) {
|
ssh_options_set(ssh, SSH_OPTIONS_AI_FAMILY, &opts->ai_family) < 0) {
|
||||||
priv_set_errv("failed to set address family");
|
priv_set_errv("failed to set address family");
|
||||||
@@ -114,15 +133,32 @@ static int ssh_set_opts(ssh_session ssh, struct mscp_ssh_opts *opts)
|
|||||||
|
|
||||||
static int ssh_authenticate(ssh_session ssh, struct mscp_ssh_opts *opts)
|
static int ssh_authenticate(ssh_session ssh, struct mscp_ssh_opts *opts)
|
||||||
{
|
{
|
||||||
int auth_bit_mask;
|
static int auth_bit_mask;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* try publickey auth first */
|
if (auth_bit_mask == 0) {
|
||||||
char *p = opts->passphrase ? opts->passphrase : NULL;
|
/* the first authentication attempt. try none auth to
|
||||||
if (ssh_userauth_publickey_auto(ssh, NULL, p) == SSH_AUTH_SUCCESS)
|
* get available auth methods. */
|
||||||
return 0;
|
if (ssh_userauth_none(ssh, NULL) == SSH_AUTH_SUCCESS)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* save auth_bit_mask for further authentications.
|
||||||
|
* when an authentication succeeds, auth_bit_mask is
|
||||||
|
* overwritten with the suceeded authentication method
|
||||||
|
* to avoid authentication failures by other methods.
|
||||||
|
*/
|
||||||
|
auth_bit_mask = ssh_userauth_list(ssh, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auth_bit_mask & SSH_AUTH_METHOD_PUBLICKEY) {
|
||||||
|
char *p = opts->passphrase ? opts->passphrase : NULL;
|
||||||
|
if (ssh_userauth_publickey_auto(ssh, NULL, p) == SSH_AUTH_SUCCESS) {
|
||||||
|
auth_bit_mask = SSH_AUTH_METHOD_PUBLICKEY;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
auth_bit_mask = ssh_userauth_list(ssh, NULL);
|
|
||||||
if (auth_bit_mask & SSH_AUTH_METHOD_PASSWORD) {
|
if (auth_bit_mask & SSH_AUTH_METHOD_PASSWORD) {
|
||||||
if (!opts->password) {
|
if (!opts->password) {
|
||||||
char buf[128] = {};
|
char buf[128] = {};
|
||||||
@@ -136,14 +172,17 @@ static int ssh_authenticate(ssh_session ssh, struct mscp_ssh_opts *opts)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ssh_userauth_password(ssh, NULL, opts->password) == SSH_AUTH_SUCCESS)
|
if (ssh_userauth_password(ssh, NULL, opts->password) == SSH_AUTH_SUCCESS) {
|
||||||
return 0;
|
auth_bit_mask = SSH_AUTH_METHOD_PASSWORD;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auth_bit_mask = ssh_userauth_list(ssh, NULL);
|
|
||||||
if (auth_bit_mask & SSH_AUTH_METHOD_INTERACTIVE) {
|
if (auth_bit_mask & SSH_AUTH_METHOD_INTERACTIVE) {
|
||||||
if (ssh_authenticate_kbdint(ssh) == SSH_AUTH_SUCCESS)
|
if (ssh_authenticate_kbdint(ssh) == SSH_AUTH_SUCCESS) {
|
||||||
return 0;
|
auth_bit_mask = SSH_AUTH_METHOD_INTERACTIVE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
244
test/test_e2e.py
244
test/test_e2e.py
@@ -9,28 +9,71 @@ import getpass
|
|||||||
import datetime
|
import datetime
|
||||||
import time
|
import time
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
from subprocess import check_call, CalledProcessError
|
from subprocess import check_output, CalledProcessError, STDOUT
|
||||||
from util import File, check_same_md5sum
|
from util import File, check_same_md5sum
|
||||||
|
|
||||||
|
|
||||||
def run2ok(args, env = None, quiet = False):
|
def run2ok(args, env = None) -> str:
|
||||||
cmd = list(map(str, args))
|
cmd = list(map(str, args))
|
||||||
if not quiet:
|
print("cmd: {}".format(" ".join(cmd)))
|
||||||
print("cmd: {}".format(" ".join(cmd)))
|
out = check_output(cmd, env = env, stderr = STDOUT).decode()
|
||||||
check_call(cmd, env = env)
|
print(out)
|
||||||
|
return out
|
||||||
|
|
||||||
def run2ng(args, env = None, timeout = None, quiet = False):
|
def run2ng(args, env = None, timeout = None):
|
||||||
if timeout:
|
if timeout:
|
||||||
args = ["timeout", "-s", "INT", timeout] + args
|
args = ["timeout", "-s", "INT", timeout] + args
|
||||||
cmd = list(map(str, args))
|
cmd = list(map(str, args))
|
||||||
if not quiet:
|
print("cmd: {}".format(" ".join(cmd)))
|
||||||
print("cmd: {}".format(" ".join(cmd)))
|
with pytest.raises(CalledProcessError) as execinfo:
|
||||||
with pytest.raises(CalledProcessError):
|
check_output(cmd, env = env, stderr = STDOUT)
|
||||||
check_call(cmd, env = env)
|
out = execinfo.value.stdout.decode()
|
||||||
|
print(out)
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
def cleanup_files():
|
||||||
|
"""
|
||||||
|
Cleanup files having the following `prefixes` or matching `paths`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
yield
|
||||||
|
|
||||||
|
prefixes = [
|
||||||
|
"src", "dst",
|
||||||
|
"non_existent_dstdir",
|
||||||
|
]
|
||||||
|
paths = [
|
||||||
|
"/mscp-test-src", "/tmp/mscp-test-src",
|
||||||
|
"{}/src".format(os.environ["HOME"]),
|
||||||
|
"{}/dst".format(os.environ["HOME"]),
|
||||||
|
"/tmp/mscp_test_ssh_config",
|
||||||
|
"/home/test/dst",
|
||||||
|
"/home/test/src",
|
||||||
|
"checkpoint",
|
||||||
|
]
|
||||||
|
|
||||||
|
def remove(path):
|
||||||
|
print(f"cleanup remove: {fname}")
|
||||||
|
if os.path.isdir(path):
|
||||||
|
shutil.rmtree(path)
|
||||||
|
else:
|
||||||
|
os.remove(path)
|
||||||
|
|
||||||
|
for fname in os.listdir(os.getcwd()):
|
||||||
|
for prefix in prefixes:
|
||||||
|
if fname.startswith(prefix):
|
||||||
|
remove(fname)
|
||||||
|
break
|
||||||
|
|
||||||
|
for path in paths:
|
||||||
|
if os.path.exists(path):
|
||||||
|
remove(path)
|
||||||
|
|
||||||
|
|
||||||
""" usage test """
|
""" usage test """
|
||||||
|
|
||||||
@@ -72,8 +115,7 @@ def test_single_copy(mscp, src_prefix, dst_prefix, src, dst):
|
|||||||
src.make()
|
src.make()
|
||||||
run2ok([mscp, "-vvv", src_prefix + src.path, dst_prefix + dst.path])
|
run2ok([mscp, "-vvv", src_prefix + src.path, dst_prefix + dst.path])
|
||||||
assert check_same_md5sum(src, dst)
|
assert check_same_md5sum(src, dst)
|
||||||
src.cleanup()
|
|
||||||
dst.cleanup()
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
||||||
def test_failed_to_copy_nonexistent_file(mscp, src_prefix, dst_prefix):
|
def test_failed_to_copy_nonexistent_file(mscp, src_prefix, dst_prefix):
|
||||||
@@ -94,10 +136,6 @@ def test_double_copy(mscp, src_prefix, dst_prefix, s1, s2, d1, d2):
|
|||||||
run2ok([mscp, "-vvv", src_prefix + s1.path, src_prefix + s2.path, dst_prefix + "dst"])
|
run2ok([mscp, "-vvv", src_prefix + s1.path, src_prefix + s2.path, dst_prefix + "dst"])
|
||||||
assert check_same_md5sum(s1, d1)
|
assert check_same_md5sum(s1, d1)
|
||||||
assert check_same_md5sum(s2, d2)
|
assert check_same_md5sum(s2, d2)
|
||||||
s1.cleanup()
|
|
||||||
s2.cleanup()
|
|
||||||
d1.cleanup()
|
|
||||||
d2.cleanup()
|
|
||||||
|
|
||||||
|
|
||||||
remote_v6_prefix = "[::1]:{}/".format(os.getcwd())
|
remote_v6_prefix = "[::1]:{}/".format(os.getcwd())
|
||||||
@@ -113,10 +151,6 @@ def test_double_copy_with_ipv6_notation(mscp, src_prefix, dst_prefix, s1, s2, d1
|
|||||||
src_prefix + s1.path, src_prefix + s2.path, dst_prefix + "dst"])
|
src_prefix + s1.path, src_prefix + s2.path, dst_prefix + "dst"])
|
||||||
assert check_same_md5sum(s1, d1)
|
assert check_same_md5sum(s1, d1)
|
||||||
assert check_same_md5sum(s2, d2)
|
assert check_same_md5sum(s2, d2)
|
||||||
s1.cleanup()
|
|
||||||
s2.cleanup()
|
|
||||||
d1.cleanup()
|
|
||||||
d2.cleanup()
|
|
||||||
|
|
||||||
|
|
||||||
remote_user_v6_prefix = "{}@[::1]:{}/".format(getpass.getuser(), os.getcwd())
|
remote_user_v6_prefix = "{}@[::1]:{}/".format(getpass.getuser(), os.getcwd())
|
||||||
@@ -133,11 +167,6 @@ def test_double_copy_with_user_and_ipv6_notation(mscp, src_prefix, dst_prefix,
|
|||||||
src_prefix + s1.path, src_prefix + s2.path, dst_prefix + "dst"])
|
src_prefix + s1.path, src_prefix + s2.path, dst_prefix + "dst"])
|
||||||
assert check_same_md5sum(s1, d1)
|
assert check_same_md5sum(s1, d1)
|
||||||
assert check_same_md5sum(s2, d2)
|
assert check_same_md5sum(s2, d2)
|
||||||
s1.cleanup()
|
|
||||||
s2.cleanup()
|
|
||||||
d1.cleanup()
|
|
||||||
d2.cleanup()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
param_dir_copy = [
|
param_dir_copy = [
|
||||||
@@ -177,10 +206,6 @@ def test_dir_copy(mscp, src_prefix, dst_prefix, src_dir, dst_dir, src, dst, twic
|
|||||||
for sf, df in zip(src, twice):
|
for sf, df in zip(src, twice):
|
||||||
assert check_same_md5sum(sf, df)
|
assert check_same_md5sum(sf, df)
|
||||||
|
|
||||||
for sf, df, tf in zip(src, dst, twice):
|
|
||||||
sf.cleanup()
|
|
||||||
df.cleanup()
|
|
||||||
tf.cleanup()
|
|
||||||
|
|
||||||
|
|
||||||
param_dir_copy_single = [
|
param_dir_copy_single = [
|
||||||
@@ -196,8 +221,7 @@ def test_dir_copy_single(mscp, src_prefix, dst_prefix, src_dir, dst_dir, src, ds
|
|||||||
os.mkdir(dst_dir)
|
os.mkdir(dst_dir)
|
||||||
run2ok([mscp, "-vvv", src_prefix + src_dir, dst_prefix + dst_dir])
|
run2ok([mscp, "-vvv", src_prefix + src_dir, dst_prefix + dst_dir])
|
||||||
assert check_same_md5sum(src, dst)
|
assert check_same_md5sum(src, dst)
|
||||||
src.cleanup()
|
|
||||||
dst.cleanup()
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
||||||
def test_override_single_file(mscp, src_prefix, dst_prefix):
|
def test_override_single_file(mscp, src_prefix, dst_prefix):
|
||||||
@@ -208,8 +232,6 @@ def test_override_single_file(mscp, src_prefix, dst_prefix):
|
|||||||
run2ok([mscp, "-vvv", src_prefix + src.path, dst_prefix + dst.path])
|
run2ok([mscp, "-vvv", src_prefix + src.path, dst_prefix + dst.path])
|
||||||
assert check_same_md5sum(src, dst)
|
assert check_same_md5sum(src, dst)
|
||||||
|
|
||||||
src.cleanup()
|
|
||||||
dst.cleanup()
|
|
||||||
|
|
||||||
absolute_remote_prefix = "localhost:"
|
absolute_remote_prefix = "localhost:"
|
||||||
param_absolute_remote_prefix = [
|
param_absolute_remote_prefix = [
|
||||||
@@ -223,8 +245,7 @@ def test_copy_file_under_root_to_dir(mscp, src_prefix, dst_prefix):
|
|||||||
run2ok([mscp, "-vvv", src_prefix + src.path,
|
run2ok([mscp, "-vvv", src_prefix + src.path,
|
||||||
dst_prefix + os.path.dirname(dst.path)])
|
dst_prefix + os.path.dirname(dst.path)])
|
||||||
assert check_same_md5sum(src, dst)
|
assert check_same_md5sum(src, dst)
|
||||||
src.cleanup()
|
|
||||||
dst.cleanup(preserve_dir = True)
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
||||||
def test_dst_has_suffix_slash(mscp, src_prefix, dst_prefix):
|
def test_dst_has_suffix_slash(mscp, src_prefix, dst_prefix):
|
||||||
@@ -233,7 +254,6 @@ def test_dst_has_suffix_slash(mscp, src_prefix, dst_prefix):
|
|||||||
mscp should create dir/ and put dir/src-file-name.
|
mscp should create dir/ and put dir/src-file-name.
|
||||||
"""
|
"""
|
||||||
dstdir = "non_existent_dstdir/"
|
dstdir = "non_existent_dstdir/"
|
||||||
shutil.rmtree(dstdir, ignore_errors=True)
|
|
||||||
|
|
||||||
src = File("src", size = 1024 * 1024).make()
|
src = File("src", size = 1024 * 1024).make()
|
||||||
dst = File(f"{dstdir}/src")
|
dst = File(f"{dstdir}/src")
|
||||||
@@ -242,8 +262,7 @@ def test_dst_has_suffix_slash(mscp, src_prefix, dst_prefix):
|
|||||||
dst_prefix + dstdir])
|
dst_prefix + dstdir])
|
||||||
|
|
||||||
assert check_same_md5sum(src, dst)
|
assert check_same_md5sum(src, dst)
|
||||||
src.cleanup()
|
|
||||||
dst.cleanup()
|
|
||||||
|
|
||||||
param_tilde_paths = [
|
param_tilde_paths = [
|
||||||
("src", "localhost:~/dst"),
|
("src", "localhost:~/dst"),
|
||||||
@@ -268,9 +287,6 @@ def test_remote_path_contains_tilde(mscp, src_path, dst_path):
|
|||||||
run2ok([mscp, "-vvv", src_path, dst_path])
|
run2ok([mscp, "-vvv", src_path, dst_path])
|
||||||
assert check_same_md5sum(src, dst)
|
assert check_same_md5sum(src, dst)
|
||||||
|
|
||||||
src.cleanup(preserve_dir=True)
|
|
||||||
dst.cleanup(preserve_dir=True)
|
|
||||||
|
|
||||||
|
|
||||||
def test_remote_path_contains_tilde2(mscp):
|
def test_remote_path_contains_tilde2(mscp):
|
||||||
src = File("src", size = 1024 * 1024).make()
|
src = File("src", size = 1024 * 1024).make()
|
||||||
@@ -279,9 +295,6 @@ def test_remote_path_contains_tilde2(mscp):
|
|||||||
run2ok([mscp, "-vvv", src.path, f"localhost:~"])
|
run2ok([mscp, "-vvv", src.path, f"localhost:~"])
|
||||||
assert check_same_md5sum(src, dst)
|
assert check_same_md5sum(src, dst)
|
||||||
|
|
||||||
src.cleanup(preserve_dir=True)
|
|
||||||
dst.cleanup(preserve_dir=True)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
||||||
def test_min_chunk(mscp, src_prefix, dst_prefix):
|
def test_min_chunk(mscp, src_prefix, dst_prefix):
|
||||||
@@ -291,9 +304,6 @@ def test_min_chunk(mscp, src_prefix, dst_prefix):
|
|||||||
run2ok([mscp, "-vvv", "-s", 32768, src_prefix + src.path, dst_prefix + dst.path])
|
run2ok([mscp, "-vvv", "-s", 32768, src_prefix + src.path, dst_prefix + dst.path])
|
||||||
assert check_same_md5sum(src, dst)
|
assert check_same_md5sum(src, dst)
|
||||||
|
|
||||||
src.cleanup()
|
|
||||||
dst.cleanup()
|
|
||||||
|
|
||||||
|
|
||||||
def is_alpine():
|
def is_alpine():
|
||||||
if os.path.exists("/etc/os-release"):
|
if os.path.exists("/etc/os-release"):
|
||||||
@@ -328,8 +338,7 @@ def test_glob_src_path(mscp, src_prefix, dst_prefix,
|
|||||||
run2ok([mscp, "-vvv", src_prefix + src_glob_path, dst_prefix + dst_path])
|
run2ok([mscp, "-vvv", src_prefix + src_glob_path, dst_prefix + dst_path])
|
||||||
for src, dst in zip(srcs, dsts):
|
for src, dst in zip(srcs, dsts):
|
||||||
assert check_same_md5sum(src, dst)
|
assert check_same_md5sum(src, dst)
|
||||||
src.cleanup()
|
|
||||||
dst.cleanup()
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
||||||
def test_thread_affinity(mscp, src_prefix, dst_prefix):
|
def test_thread_affinity(mscp, src_prefix, dst_prefix):
|
||||||
@@ -340,8 +349,6 @@ def test_thread_affinity(mscp, src_prefix, dst_prefix):
|
|||||||
src_prefix + src.path, dst_prefix + dst.path])
|
src_prefix + src.path, dst_prefix + dst.path])
|
||||||
assert check_same_md5sum(src, dst)
|
assert check_same_md5sum(src, dst)
|
||||||
|
|
||||||
src.cleanup()
|
|
||||||
dst.cleanup()
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
||||||
def test_cannot_override_file_with_dir(mscp, src_prefix, dst_prefix):
|
def test_cannot_override_file_with_dir(mscp, src_prefix, dst_prefix):
|
||||||
@@ -350,8 +357,6 @@ def test_cannot_override_file_with_dir(mscp, src_prefix, dst_prefix):
|
|||||||
|
|
||||||
run2ng([mscp, "-vvv", src_prefix + src.path, dst_prefix + "dst/src"])
|
run2ng([mscp, "-vvv", src_prefix + src.path, dst_prefix + "dst/src"])
|
||||||
|
|
||||||
src.cleanup()
|
|
||||||
dst.cleanup()
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
||||||
def test_transfer_zero_bytes(mscp, src_prefix, dst_prefix):
|
def test_transfer_zero_bytes(mscp, src_prefix, dst_prefix):
|
||||||
@@ -359,8 +364,6 @@ def test_transfer_zero_bytes(mscp, src_prefix, dst_prefix):
|
|||||||
dst = File("dst")
|
dst = File("dst")
|
||||||
run2ok([mscp, "-vvv", src_prefix + src.path, dst_prefix + "dst"])
|
run2ok([mscp, "-vvv", src_prefix + src.path, dst_prefix + "dst"])
|
||||||
assert os.path.exists("dst")
|
assert os.path.exists("dst")
|
||||||
src.cleanup()
|
|
||||||
dst.cleanup()
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
||||||
def test_override_dst_having_larger_size(mscp, src_prefix, dst_prefix):
|
def test_override_dst_having_larger_size(mscp, src_prefix, dst_prefix):
|
||||||
@@ -368,8 +371,6 @@ def test_override_dst_having_larger_size(mscp, src_prefix, dst_prefix):
|
|||||||
dst = File("dst", size = 1024 * 1024 * 2).make()
|
dst = File("dst", size = 1024 * 1024 * 2).make()
|
||||||
run2ok([mscp, "-vvv", src_prefix + src.path, dst_prefix + "dst"])
|
run2ok([mscp, "-vvv", src_prefix + src.path, dst_prefix + "dst"])
|
||||||
assert check_same_md5sum(src, dst)
|
assert check_same_md5sum(src, dst)
|
||||||
src.cleanup()
|
|
||||||
dst.cleanup()
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
||||||
def test_dont_truncate_dst(mscp, src_prefix, dst_prefix):
|
def test_dont_truncate_dst(mscp, src_prefix, dst_prefix):
|
||||||
@@ -378,7 +379,7 @@ def test_dont_truncate_dst(mscp, src_prefix, dst_prefix):
|
|||||||
run2ok([mscp, "-vvv", src_prefix + f.path, dst_prefix + f.path])
|
run2ok([mscp, "-vvv", src_prefix + f.path, dst_prefix + f.path])
|
||||||
md5_after = f.md5sum()
|
md5_after = f.md5sum()
|
||||||
assert md5_before == md5_after
|
assert md5_before == md5_after
|
||||||
f.cleanup()
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
||||||
def test_copy_readonly_file(mscp, src_prefix, dst_prefix):
|
def test_copy_readonly_file(mscp, src_prefix, dst_prefix):
|
||||||
@@ -392,8 +393,6 @@ def test_copy_readonly_file(mscp, src_prefix, dst_prefix):
|
|||||||
dst = File("dst")
|
dst = File("dst")
|
||||||
run2ok([mscp, "-vvv", src_prefix + src.path, dst_prefix + dst.path])
|
run2ok([mscp, "-vvv", src_prefix + src.path, dst_prefix + dst.path])
|
||||||
assert check_same_md5sum(src, dst)
|
assert check_same_md5sum(src, dst)
|
||||||
src.cleanup()
|
|
||||||
dst.cleanup()
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
||||||
def test_dont_make_conns_more_than_chunks(mscp, src_prefix, dst_prefix):
|
def test_dont_make_conns_more_than_chunks(mscp, src_prefix, dst_prefix):
|
||||||
@@ -410,8 +409,7 @@ def test_dont_make_conns_more_than_chunks(mscp, src_prefix, dst_prefix):
|
|||||||
end = time.time()
|
end = time.time()
|
||||||
for s, d in zip(srcs, dsts):
|
for s, d in zip(srcs, dsts):
|
||||||
assert check_same_md5sum(s, d)
|
assert check_same_md5sum(s, d)
|
||||||
shutil.rmtree("src")
|
|
||||||
shutil.rmtree("dst")
|
|
||||||
assert((end - start) < 10)
|
assert((end - start) < 10)
|
||||||
|
|
||||||
|
|
||||||
@@ -425,24 +423,51 @@ def test_bwlimit(mscp, src_prefix, dst_prefix):
|
|||||||
run2ok([mscp, "-vvv", "-L", "100m", src_prefix + "src", dst_prefix + "dst"])
|
run2ok([mscp, "-vvv", "-L", "100m", src_prefix + "src", dst_prefix + "dst"])
|
||||||
end = datetime.datetime.now().timestamp()
|
end = datetime.datetime.now().timestamp()
|
||||||
assert check_same_md5sum(src, dst)
|
assert check_same_md5sum(src, dst)
|
||||||
src.cleanup()
|
|
||||||
dst.cleanup()
|
|
||||||
assert end - start > 7
|
assert end - start > 7
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
||||||
|
def test_bind_ng(mscp, src_prefix, dst_prefix):
|
||||||
|
"""Bind to invalid address should fail."""
|
||||||
|
out = run2ng([mscp, "-vvv", "-ddd", "-B", "192.168.10.10",
|
||||||
|
src_prefix + "src", dst_prefix + "dst"])
|
||||||
|
assert ("Cannot assign requested address" in out or
|
||||||
|
"Address not available" in out)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
||||||
|
def test_bind_ok(mscp, src_prefix, dst_prefix):
|
||||||
|
"""Bind to multiple lo addresses and check all of them used """
|
||||||
|
|
||||||
|
srcs = [ File(f"src-{x}", size = 128).make() for x in range(10) ]
|
||||||
|
src_paths = [ src_prefix + src.path for src in srcs ]
|
||||||
|
|
||||||
|
out = run2ok([mscp, "-v", "-ddd",
|
||||||
|
"-B", "127.0.0.10", "-B", "127.0.0.20", "-B", "127.0.0.30",
|
||||||
|
] +
|
||||||
|
src_paths + [dst_prefix + "dst/"])
|
||||||
|
|
||||||
|
for src in srcs:
|
||||||
|
dst = File(f"dst/{src.path}")
|
||||||
|
assert check_same_md5sum(src, dst)
|
||||||
|
|
||||||
|
assert "127.0.0.10" in out
|
||||||
|
assert "127.0.0.20" in out
|
||||||
|
assert "127.0.0.30" in out
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
||||||
@pytest.mark.parametrize("src, dst", param_single_copy)
|
@pytest.mark.parametrize("src, dst", param_single_copy)
|
||||||
def test_set_port_ng(mscp, src_prefix, dst_prefix, src, dst):
|
def test_set_port_ng(mscp, src_prefix, dst_prefix, src, dst):
|
||||||
src.make()
|
src.make()
|
||||||
run2ng([mscp, "-vvv", "-P", 21, src_prefix + src.path, dst_prefix + dst.path])
|
run2ng([mscp, "-vvv", "-P", 21, src_prefix + src.path, dst_prefix + dst.path])
|
||||||
src.cleanup()
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
||||||
@pytest.mark.parametrize("src, dst", param_single_copy)
|
@pytest.mark.parametrize("src, dst", param_single_copy)
|
||||||
def test_set_port_ok(mscp, src_prefix, dst_prefix, src, dst):
|
def test_set_port_ok(mscp, src_prefix, dst_prefix, src, dst):
|
||||||
src.make()
|
src.make()
|
||||||
run2ok([mscp, "-vvv", "-P", 8022, src_prefix + src.path, dst_prefix + dst.path])
|
run2ok([mscp, "-vvv", "-P", 8022, src_prefix + src.path, dst_prefix + dst.path])
|
||||||
src.cleanup()
|
|
||||||
|
|
||||||
def test_v4only(mscp):
|
def test_v4only(mscp):
|
||||||
src = File("src", size = 1024).make()
|
src = File("src", size = 1024).make()
|
||||||
@@ -450,8 +475,6 @@ def test_v4only(mscp):
|
|||||||
dst_prefix = "localhost:{}/".format(os.getcwd())
|
dst_prefix = "localhost:{}/".format(os.getcwd())
|
||||||
run2ok([mscp, "-vvv", "-4", src.path, dst_prefix + dst.path])
|
run2ok([mscp, "-vvv", "-4", src.path, dst_prefix + dst.path])
|
||||||
assert check_same_md5sum(src, dst)
|
assert check_same_md5sum(src, dst)
|
||||||
src.cleanup()
|
|
||||||
dst.cleanup()
|
|
||||||
|
|
||||||
def test_v6only(mscp):
|
def test_v6only(mscp):
|
||||||
src = File("src", size = 1024).make()
|
src = File("src", size = 1024).make()
|
||||||
@@ -459,34 +482,26 @@ def test_v6only(mscp):
|
|||||||
dst_prefix = "ip6-localhost:{}/".format(os.getcwd())
|
dst_prefix = "ip6-localhost:{}/".format(os.getcwd())
|
||||||
run2ok([mscp, "-vvv", "-6", src.path, dst_prefix + dst.path])
|
run2ok([mscp, "-vvv", "-6", src.path, dst_prefix + dst.path])
|
||||||
assert check_same_md5sum(src, dst)
|
assert check_same_md5sum(src, dst)
|
||||||
src.cleanup()
|
|
||||||
dst.cleanup()
|
|
||||||
|
|
||||||
def test_v4_to_v6_should_fail(mscp):
|
def test_v4_to_v6_should_fail(mscp):
|
||||||
src = File("src", size = 1024).make()
|
src = File("src", size = 1024).make()
|
||||||
dst = File("dst")
|
dst = File("dst")
|
||||||
dst_prefix = "[::1]:{}/".format(os.getcwd())
|
dst_prefix = "[::1]:{}/".format(os.getcwd())
|
||||||
run2ng([mscp, "-vvv", "-4", src.path, dst_prefix + dst.path])
|
run2ng([mscp, "-vvv", "-4", src.path, dst_prefix + dst.path])
|
||||||
src.cleanup()
|
|
||||||
|
|
||||||
def test_v6_to_v4_should_fail(mscp):
|
def test_v6_to_v4_should_fail(mscp):
|
||||||
src = File("src", size = 1024).make()
|
src = File("src", size = 1024).make()
|
||||||
dst = File("dst")
|
dst = File("dst")
|
||||||
dst_prefix = "127.0.0.1:{}/".format(os.getcwd())
|
dst_prefix = "127.0.0.1:{}/".format(os.getcwd())
|
||||||
run2ng([mscp, "-vvv", "-6", src.path, dst_prefix + dst.path])
|
run2ng([mscp, "-vvv", "-6", src.path, dst_prefix + dst.path])
|
||||||
src.cleanup()
|
|
||||||
|
|
||||||
def test_quiet_mode(capsys, mscp):
|
def test_quiet_mode(mscp):
|
||||||
src = File("src", size = 1024).make()
|
src = File("src", size = 1024).make()
|
||||||
dst = File("dst")
|
dst = File("dst")
|
||||||
dst_prefix = "127.0.0.1:{}/".format(os.getcwd())
|
dst_prefix = "127.0.0.1:{}/".format(os.getcwd())
|
||||||
run2ok([mscp, "-vvv", "-q", src.path, dst_prefix + dst.path], quiet=True)
|
out = run2ok([mscp, "-vvv", "-q", src.path, dst_prefix + dst.path])
|
||||||
assert check_same_md5sum(src, dst)
|
assert check_same_md5sum(src, dst)
|
||||||
src.cleanup()
|
assert not out
|
||||||
dst.cleanup()
|
|
||||||
captured = capsys.readouterr()
|
|
||||||
assert not captured.out
|
|
||||||
assert not captured.err
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
||||||
def test_set_conn_interval(mscp, src_prefix, dst_prefix):
|
def test_set_conn_interval(mscp, src_prefix, dst_prefix):
|
||||||
@@ -499,8 +514,6 @@ def test_set_conn_interval(mscp, src_prefix, dst_prefix):
|
|||||||
|
|
||||||
for src, dst in zip(srcs, dsts):
|
for src, dst in zip(srcs, dsts):
|
||||||
assert check_same_md5sum(src, dst)
|
assert check_same_md5sum(src, dst)
|
||||||
src.cleanup()
|
|
||||||
dst.cleanup()
|
|
||||||
|
|
||||||
compressions = ["yes", "no", "none"]
|
compressions = ["yes", "no", "none"]
|
||||||
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
||||||
@@ -510,8 +523,6 @@ def test_compression(mscp, src_prefix, dst_prefix, compress):
|
|||||||
dst = File("dst", size = 1024 * 1024 * 2).make()
|
dst = File("dst", size = 1024 * 1024 * 2).make()
|
||||||
run2ok([mscp, "-vvv", "-C", compress, src_prefix + src.path, dst_prefix + "dst"])
|
run2ok([mscp, "-vvv", "-C", compress, src_prefix + src.path, dst_prefix + "dst"])
|
||||||
assert check_same_md5sum(src, dst)
|
assert check_same_md5sum(src, dst)
|
||||||
src.cleanup()
|
|
||||||
dst.cleanup()
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
||||||
def test_ccalgo(mscp, src_prefix, dst_prefix):
|
def test_ccalgo(mscp, src_prefix, dst_prefix):
|
||||||
@@ -548,8 +559,7 @@ def test_config_ok(mscp, src_prefix, dst_prefix):
|
|||||||
|
|
||||||
os.remove(config)
|
os.remove(config)
|
||||||
assert check_same_md5sum(src, dst)
|
assert check_same_md5sum(src, dst)
|
||||||
src.cleanup()
|
|
||||||
dst.cleanup()
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("src_prefix, dst_prefix", param_testhost_prefix)
|
@pytest.mark.parametrize("src_prefix, dst_prefix", param_testhost_prefix)
|
||||||
def test_config_ng(mscp, src_prefix, dst_prefix):
|
def test_config_ng(mscp, src_prefix, dst_prefix):
|
||||||
@@ -563,8 +573,6 @@ def test_config_ng(mscp, src_prefix, dst_prefix):
|
|||||||
src_prefix + src.path, dst_prefix + "dst"])
|
src_prefix + src.path, dst_prefix + "dst"])
|
||||||
|
|
||||||
os.remove(config)
|
os.remove(config)
|
||||||
src.cleanup()
|
|
||||||
dst.cleanup()
|
|
||||||
|
|
||||||
|
|
||||||
param_valid_option_ok = [
|
param_valid_option_ok = [
|
||||||
@@ -581,8 +589,6 @@ def test_inline_option_ok(mscp, src_prefix, dst_prefix, option):
|
|||||||
run2ok([mscp, "-vvv"] + option +
|
run2ok([mscp, "-vvv"] + option +
|
||||||
[src_prefix + src.path, dst_prefix + dst.path])
|
[src_prefix + src.path, dst_prefix + dst.path])
|
||||||
assert check_same_md5sum(src, dst)
|
assert check_same_md5sum(src, dst)
|
||||||
src.cleanup()
|
|
||||||
dst.cleanup()
|
|
||||||
|
|
||||||
|
|
||||||
param_valid_option_ng = [
|
param_valid_option_ng = [
|
||||||
@@ -597,7 +603,6 @@ def test_inline_option_ng(mscp, src_prefix, dst_prefix, option):
|
|||||||
dst = File("dst")
|
dst = File("dst")
|
||||||
run2ng([mscp, "-vvv"] + option +
|
run2ng([mscp, "-vvv"] + option +
|
||||||
[src_prefix + src.path, dst_prefix + dst.path])
|
[src_prefix + src.path, dst_prefix + dst.path])
|
||||||
src.cleanup()
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
||||||
@@ -610,8 +615,6 @@ def test_porxyjump_ok(mscp, src_prefix, dst_prefix):
|
|||||||
"-J", "localhost:8022",
|
"-J", "localhost:8022",
|
||||||
src_prefix + src.path, dst_prefix + dst.path])
|
src_prefix + src.path, dst_prefix + dst.path])
|
||||||
assert check_same_md5sum(src, dst)
|
assert check_same_md5sum(src, dst)
|
||||||
src.cleanup()
|
|
||||||
dst.cleanup()
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
||||||
@@ -623,7 +626,6 @@ def test_porxyjump_ng(mscp, src_prefix, dst_prefix):
|
|||||||
run2ng([mscp, "-n", 4, "-s", 1024 * 1024, "-vvv",
|
run2ng([mscp, "-n", 4, "-s", 1024 * 1024, "-vvv",
|
||||||
"-J", "invaliduser@localhost:8022",
|
"-J", "invaliduser@localhost:8022",
|
||||||
src_prefix + src.path, dst_prefix + dst.path])
|
src_prefix + src.path, dst_prefix + dst.path])
|
||||||
src.cleanup()
|
|
||||||
|
|
||||||
# username test assumes that this test runs inside a container, see Dockerfiles
|
# username test assumes that this test runs inside a container, see Dockerfiles
|
||||||
def test_specify_passphrase_via_env(mscp):
|
def test_specify_passphrase_via_env(mscp):
|
||||||
@@ -634,8 +636,6 @@ def test_specify_passphrase_via_env(mscp):
|
|||||||
run2ok([mscp, "-vvv", "-l", "test", "-i", "/home/test/.ssh/id_rsa_test",
|
run2ok([mscp, "-vvv", "-l", "test", "-i", "/home/test/.ssh/id_rsa_test",
|
||||||
src.path, "localhost:" + dst.path], env = env)
|
src.path, "localhost:" + dst.path], env = env)
|
||||||
assert check_same_md5sum(src, dst)
|
assert check_same_md5sum(src, dst)
|
||||||
src.cleanup()
|
|
||||||
dst.cleanup()
|
|
||||||
|
|
||||||
def test_specify_invalid_passphrase_via_env(mscp):
|
def test_specify_invalid_passphrase_via_env(mscp):
|
||||||
src = File(os.getcwd() + "/src", size = 1024).make()
|
src = File(os.getcwd() + "/src", size = 1024).make()
|
||||||
@@ -644,7 +644,6 @@ def test_specify_invalid_passphrase_via_env(mscp):
|
|||||||
env["MSCP_SSH_AUTH_PASSPHRASE"] = "invalid-keypassphrase"
|
env["MSCP_SSH_AUTH_PASSPHRASE"] = "invalid-keypassphrase"
|
||||||
run2ng([mscp, "-vvv", "-l", "test", "-i", "/home/test/.ssh/id_rsa_test",
|
run2ng([mscp, "-vvv", "-l", "test", "-i", "/home/test/.ssh/id_rsa_test",
|
||||||
src.path, "localhost:" + dst.path], env = env)
|
src.path, "localhost:" + dst.path], env = env)
|
||||||
src.cleanup()
|
|
||||||
|
|
||||||
def test_specify_password_via_env(mscp):
|
def test_specify_password_via_env(mscp):
|
||||||
src = File(os.getcwd() + "/src", size = 1024).make()
|
src = File(os.getcwd() + "/src", size = 1024).make()
|
||||||
@@ -654,8 +653,6 @@ def test_specify_password_via_env(mscp):
|
|||||||
run2ok([mscp, "-vvv", "-l", "test",
|
run2ok([mscp, "-vvv", "-l", "test",
|
||||||
src.path, "localhost:" + dst.path], env = env)
|
src.path, "localhost:" + dst.path], env = env)
|
||||||
assert check_same_md5sum(src, dst)
|
assert check_same_md5sum(src, dst)
|
||||||
src.cleanup()
|
|
||||||
dst.cleanup()
|
|
||||||
|
|
||||||
def test_specify_invalid_password_via_env(mscp):
|
def test_specify_invalid_password_via_env(mscp):
|
||||||
src = File(os.getcwd() + "/src", size = 1024).make()
|
src = File(os.getcwd() + "/src", size = 1024).make()
|
||||||
@@ -664,7 +661,44 @@ def test_specify_invalid_password_via_env(mscp):
|
|||||||
env["MSCP_SSH_AUTH_PASSWORD"] = "invalid-userpassword"
|
env["MSCP_SSH_AUTH_PASSWORD"] = "invalid-userpassword"
|
||||||
run2ng([mscp, "-vvv", "-l", "test",
|
run2ng([mscp, "-vvv", "-l", "test",
|
||||||
src.path, "localhost:" + dst.path], env = env)
|
src.path, "localhost:" + dst.path], env = env)
|
||||||
src.cleanup()
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def move_pubkey_temporally():
|
||||||
|
"""
|
||||||
|
mv ~/.ssh/id_* to id_rsa.bak before test, and move it back after test.
|
||||||
|
"""
|
||||||
|
|
||||||
|
sshdir = os.path.join(os.environ["HOME"], ".ssh")
|
||||||
|
|
||||||
|
# move pubkeys to /tmp
|
||||||
|
moved = []
|
||||||
|
for fname in os.listdir(sshdir):
|
||||||
|
if re.match(r"^id_[a-z0-9]+$", fname):
|
||||||
|
moved.append(fname)
|
||||||
|
shutil.move(f"{sshdir}/{fname}", f"/tmp/{fname}")
|
||||||
|
|
||||||
|
yield
|
||||||
|
|
||||||
|
# move back the keys
|
||||||
|
for fname in moved:
|
||||||
|
shutil.move(f"/tmp/{fname}", f"{sshdir}/{fname}")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
||||||
|
def test_passwordauth_without_pubkey(move_pubkey_temporally,
|
||||||
|
mscp, src_prefix, dst_prefix):
|
||||||
|
"""
|
||||||
|
make sure password auth works (by removing public keys)
|
||||||
|
"""
|
||||||
|
src = File(os.getcwd() + "/src", size = 1024).make()
|
||||||
|
dst = File("/home/test/dst")
|
||||||
|
env = os.environ
|
||||||
|
env["MSCP_SSH_AUTH_PASSWORD"] = "userpassword"
|
||||||
|
run2ok([mscp, "-vvv", "-l", "test",
|
||||||
|
src.path, "localhost:" + dst.path], env = env)
|
||||||
|
assert check_same_md5sum(src, dst)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
||||||
def test_10k_files(mscp, src_prefix, dst_prefix):
|
def test_10k_files(mscp, src_prefix, dst_prefix):
|
||||||
@@ -676,8 +710,6 @@ def test_10k_files(mscp, src_prefix, dst_prefix):
|
|||||||
run2ok([mscp, "-v", src_prefix + "src", dst_prefix + "dst"])
|
run2ok([mscp, "-v", src_prefix + "src", dst_prefix + "dst"])
|
||||||
for s, d in zip(srcs, dsts):
|
for s, d in zip(srcs, dsts):
|
||||||
assert check_same_md5sum(s, d)
|
assert check_same_md5sum(s, d)
|
||||||
shutil.rmtree("src")
|
|
||||||
shutil.rmtree("dst")
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
||||||
def test_checkpoint_dump_and_resume(mscp, src_prefix, dst_prefix):
|
def test_checkpoint_dump_and_resume(mscp, src_prefix, dst_prefix):
|
||||||
@@ -692,10 +724,6 @@ def test_checkpoint_dump_and_resume(mscp, src_prefix, dst_prefix):
|
|||||||
run2ok([mscp, "-vvv", "-R", "checkpoint"])
|
run2ok([mscp, "-vvv", "-R", "checkpoint"])
|
||||||
assert check_same_md5sum(src1, dst1)
|
assert check_same_md5sum(src1, dst1)
|
||||||
assert check_same_md5sum(src2, dst2)
|
assert check_same_md5sum(src2, dst2)
|
||||||
src1.cleanup()
|
|
||||||
src2.cleanup()
|
|
||||||
dst1.cleanup()
|
|
||||||
dst2.cleanup()
|
|
||||||
os.remove("checkpoint")
|
os.remove("checkpoint")
|
||||||
|
|
||||||
@pytest.mark.parametrize("timeout", [ 1, 2, 3, 4, 5 ])
|
@pytest.mark.parametrize("timeout", [ 1, 2, 3, 4, 5 ])
|
||||||
@@ -714,10 +742,6 @@ def test_checkpoint_interrupt_large_file(mscp, timeout, src_prefix, dst_prefix):
|
|||||||
run2ok([mscp, "-vv", "-R", "checkpoint"])
|
run2ok([mscp, "-vv", "-R", "checkpoint"])
|
||||||
assert check_same_md5sum(src1, dst1)
|
assert check_same_md5sum(src1, dst1)
|
||||||
assert check_same_md5sum(src2, dst2)
|
assert check_same_md5sum(src2, dst2)
|
||||||
src1.cleanup()
|
|
||||||
src2.cleanup()
|
|
||||||
dst1.cleanup()
|
|
||||||
dst2.cleanup()
|
|
||||||
os.remove("checkpoint")
|
os.remove("checkpoint")
|
||||||
|
|
||||||
@pytest.mark.parametrize("timeout", [ 1, 2, 3, 4, 5 ])
|
@pytest.mark.parametrize("timeout", [ 1, 2, 3, 4, 5 ])
|
||||||
@@ -743,8 +767,6 @@ def test_checkpoint_interrupt_many_files(mscp, timeout, src_prefix, dst_prefix):
|
|||||||
|
|
||||||
for src, dst in files:
|
for src, dst in files:
|
||||||
assert check_same_md5sum(src, dst)
|
assert check_same_md5sum(src, dst)
|
||||||
src.cleanup()
|
|
||||||
dst.cleanup()
|
|
||||||
|
|
||||||
os.remove("checkpoint")
|
os.remove("checkpoint")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user